ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-11-21 07:35:34
Exec Total Coverage
Lines: 99 7683 1.3%
Functions: 1 201 0.5%
Branches: 14 6805 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "allegro/color.h"
5 #include "base/files.h"
6 #include "base/pal_tables.h"
7 #include "base/qrs.h"
8 #include "base/dmap.h"
9 #include "base/cpool.h"
10 #include "base/autocombo.h"
11 #include "base/packfile.h"
12 #include "base/gui.h"
13 #include "base/combo.h"
14 #include "base/msgstr.h"
15 #include "base/zdefs.h"
16 #include "new_subscr.h"
17 #include "subscr.h"
18 #include "zq/zq_tiles.h"
19 #include "zq/zquest.h"
20 #include "tiles.h"
21 #include "zq/zq_misc.h"
22 #include "zq/zq_class.h"
23 #include "base/zsys.h"
24 #include "base/colors.h"
25 #include "base/qst.h"
26 #include "gui/jwin.h"
27 #include <base/new_menu.h>
28 #include "base/jwinfsel.h"
29 #include "hero_tiles.h"
30 #include "zq/questReport.h"
31 #include "dialog/info.h"
32 #include "dialog/scaletile.h"
33 #include "dialog/rotatetile.h"
34 #include "dialog/alert.h"
35 #include "drawing.h"
36 #include "colorname.h"
37 #include "zq/render.h"
38 #include "zinfo.h"
39 #include <fmt/format.h>
40 #include <functional>
41 #include "zq/moveinfo.h"
42 using std::set;
43
44
45 #ifdef _MSC_VER
46 #define stricmp _stricmp
47 #endif
48
49 #define HIDE_USED (show_only_unused_tiles&1)
50 #define HIDE_UNUSED (show_only_unused_tiles&2)
51 #define HIDE_BLANK (show_only_unused_tiles&4)
52 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
53
54 extern void large_dialog(DIALOG *d);
55 static void massRecolorReset4Bit();
56 static void massRecolorReset8Bit();
57 static bool massRecolorSetup(int32_t cset);
58 static void massRecolorApply(int32_t tile);
59 extern int32_t last_droplist_sel;
60 extern int32_t TilePgCursorCol, CmbPgCursorCol;
61
62 int32_t ex=0;
63 int32_t nextcombo_fake_click=0;
64 int32_t invcol=0;
65 int32_t tthighlight = 1;
66 int32_t showcolortip = 1;
67 int32_t show_quartgrid = 0, hide_grid = 0;
68
69 tiledata *newundotilebuf;
70 std::vector<newcombo> undocombobuf;
71
72 BITMAP *selection_pattern;
73 byte selection_grid[18][18];
74 byte selection_anchor=0;
75
76 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
77 BITMAP *selecting_pattern;
78 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
79
80 extern int32_t bidcomboscripts_cnt;
81 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
82
83 BITMAP *intersection_pattern;
84
85 byte relational_template[48][4]=
86 {
87 { 0, 0, 0, 0 },
88 { 0, 1, 0, 0 },
89 { 1, 0, 0, 0 },
90 { 1, 1, 0, 0 },
91 { 0, 0, 1, 0 },
92 { 0, 1, 1, 0 },
93 { 1, 0, 1, 0 },
94 { 1, 1, 1, 0 },
95 { 0, 0, 0, 1 },
96 { 0, 1, 0, 1 },
97 { 1, 0, 0, 1 },
98 { 1, 1, 0, 1 },
99 { 0, 0, 1, 1 },
100 { 0, 1, 1, 1 },
101 { 1, 0, 1, 1 },
102 { 1, 1, 1, 1 },
103 { 0, 2, 0, 2 },
104 { 1, 2, 0, 2 },
105 { 0, 2, 1, 2 },
106 { 1, 2, 1, 2 },
107 { 3, 3, 0, 0 },
108 { 3, 3, 1, 0 },
109 { 3, 3, 0, 1 },
110 { 3, 3, 1, 1 },
111 { 3, 4, 0, 2 },
112 { 3, 4, 1, 2 },
113 { 2, 0, 2, 0 },
114 { 2, 1, 2, 0 },
115 { 2, 0, 2, 1 },
116 { 2, 1, 2, 1 },
117 { 2, 2, 2, 2 },
118 { 4, 3, 2, 0 },
119 { 4, 3, 2, 1 },
120 { 4, 4, 2, 2 },
121 { 0, 0, 3, 3 },
122 { 0, 1, 3, 3 },
123 { 1, 0, 3, 3 },
124 { 1, 1, 3, 3 },
125 { 0, 2, 3, 4 },
126 { 1, 2, 3, 4 },
127 { 3, 3, 3, 3 },
128 { 3, 4, 3, 4 },
129 { 2, 0, 4, 3 },
130 { 2, 1, 4, 3 },
131 { 2, 2, 4, 4 },
132 { 4, 3, 4, 3 },
133 { 4, 4, 4, 4 },
134 { 5, 5, 5, 5 }
135 };
136
137 byte dungeon_carving_template[96][4]=
138 {
139 { 0, 0, 0, 0 },
140 { 0, 1, 0, 0 },
141 { 1, 0, 0, 0 },
142 { 1, 1, 0, 0 },
143 { 0, 0, 1, 0 },
144 { 0, 1, 1, 0 },
145 { 1, 0, 1, 0 },
146 { 1, 1, 1, 0 },
147 { 0, 0, 0, 1 },
148 { 0, 1, 0, 1 },
149 { 1, 0, 0, 1 },
150 { 1, 1, 0, 1 },
151 { 0, 0, 1, 1 },
152 { 0, 1, 1, 1 },
153 { 1, 0, 1, 1 },
154 { 1, 1, 1, 1 },
155 { 0, 2, 0, 2 },
156 { 1, 2, 0, 2 },
157 { 0, 2, 1, 2 },
158 { 1, 2, 1, 2 },
159 { 3, 3, 0, 0 },
160 { 3, 3, 1, 0 },
161 { 3, 3, 0, 1 },
162 { 3, 3, 1, 1 },
163 { 3, 4, 0, 2 },
164 { 3, 4, 1, 2 },
165 { 2, 0, 2, 0 },
166 { 2, 1, 2, 0 },
167 { 2, 0, 2, 1 },
168 { 2, 1, 2, 1 },
169 { 2, 2, 2, 2 },
170 { 4, 3, 2, 0 },
171 { 4, 3, 2, 1 },
172 { 4, 4, 2, 2 },
173 { 0, 0, 3, 3 },
174 { 0, 1, 3, 3 },
175 { 1, 0, 3, 3 },
176 { 1, 1, 3, 3 },
177 { 0, 2, 3, 4 },
178 { 1, 2, 3, 4 },
179 { 3, 3, 3, 3 },
180 { 3, 4, 3, 4 },
181 { 2, 0, 4, 3 },
182 { 2, 1, 4, 3 },
183 { 2, 2, 4, 4 },
184 { 4, 3, 4, 3 },
185 { 4, 4, 4, 4 },
186 { 5, 5, 5, 5 },
187
188 { 5, 5, 5, 5 },
189 { 6, 6, 6, 6 },
190 { 7, 7, 7, 7 },
191 { 7, 6, 7, 6 },
192 { 8, 8, 8, 8 },
193 { 16, 6, 8, 15 },
194 { 7, 7, 8, 8 },
195 { 7, 6, 8, 15 },
196 { 9, 9, 9, 9 },
197 { 6, 6, 9, 9 },
198 { 7, 17, 14, 9 },
199 { 7, 6, 14, 9 },
200 { 8, 9, 8, 9 },
201 { 16, 6, 8, 9 },
202 { 7, 17, 8, 9 },
203 { 7, 6, 8, 9 },
204 { 10, 10, 10, 10 },
205 { 7, 10, 14, 10 },
206 { 16, 10, 8, 10 },
207 { 7, 10, 8, 10 },
208 { 11, 11, 11, 11 },
209 { 11, 11, 8, 15 },
210 { 11, 11, 14, 9 },
211 { 11, 11, 8, 9 },
212 { 14, 14, 14, 14 },
213 { 14, 14, 8, 14 },
214 { 12, 12, 12, 12 },
215 { 12, 6, 12, 15 },
216 { 12, 17, 12, 9 },
217 { 12, 6, 12, 9 },
218 { 12, 10, 12, 10 },
219 { 15, 15, 15, 15 },
220 { 15, 15, 15, 9 },
221 { 15, 14, 12, 10 },
222 { 13, 13, 13, 13 },
223 { 16, 6, 13, 13 },
224 { 7, 17, 13, 13 },
225 { 7, 6, 13, 13 },
226 { 16, 16, 16, 16 },
227 { 7, 16, 16, 16 },
228 { 11, 11, 13, 13 },
229 { 11, 14, 13, 16 },
230 { 17, 17, 17, 17 },
231 { 17, 6, 17, 17 },
232 { 12, 10, 17, 16 },
233 { 15, 11, 17, 13 },
234 { 15, 14, 17, 16 },
235 { 18, 18, 18, 18 }
236 };
237
238 struct tile_move_data
239 {
240 int32_t copies;
241 int32_t dest_first;
242 int32_t dest_last;
243 int32_t src_first;
244 int32_t src_last;
245 int32_t dest_top;
246 int32_t dest_bottom;
247 int32_t src_top;
248 int32_t src_bottom;
249 int32_t src_left, src_right;
250 int32_t src_width, src_height;
251 int32_t dest_left, dest_right;
252 int32_t dest_width, dest_height;
253 int32_t rows, cols;
254 bool rect, move;
255
256 tile_move_data()
257 {
258 copies = dest_first = dest_last = src_first = src_last = dest_top =
259 dest_bottom = src_top = src_bottom = src_left = src_right =
260 src_width = src_height = dest_left = dest_right = dest_width =
261 dest_height = rows = cols = 0;
262 rect = move = false;
263 }
264
265 tile_move_data(tile_move_data const& other)
266 {
267 copy(other);
268 }
269
270 tile_move_data& operator=(tile_move_data const& other)
271 {
272 copy(other);
273 return *this;
274 }
275
276 void copy(tile_move_data const& other)
277 {
278 copies = other.copies;
279 dest_first = other.dest_first;
280 dest_last = other.dest_last;
281 src_first = other.src_first;
282 src_last = other.src_last;
283 dest_top = other.dest_top;
284 dest_bottom = other.dest_bottom;
285 src_top = other.src_top;
286 src_bottom = other.src_bottom;
287 src_left = other.src_left;
288 src_right = other.src_right;
289 src_width = other.src_width;
290 src_height = other.src_height;
291 dest_left = other.dest_left;
292 dest_right = other.dest_right;
293 dest_width = other.dest_width;
294 dest_height = other.dest_height;
295 rows = other.rows;
296 cols = other.cols;
297 rect = other.rect;
298 move = other.move;
299 }
300
301 void flip()
302 {
303 zc_swap(src_first, dest_first);
304 zc_swap(src_last, dest_last);
305 zc_swap(src_top, dest_top);
306 zc_swap(src_bottom, dest_bottom);
307 zc_swap(src_left, dest_left);
308 zc_swap(src_right, dest_right);
309 zc_swap(src_width, dest_width);
310 zc_swap(src_height, dest_height);
311 }
312 };
313 bool do_movetile_united(tile_move_data const& tmd);
314
315 struct combo_move_data
316 {
317 int32_t tile, tile2, copy1, copycnt;
318 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
319 combo_move_data(combo_move_data const& other)
320 {
321 copy(other);
322 }
323 combo_move_data& operator=(combo_move_data const& other)
324 {
325 copy(other);
326 return *this;
327 }
328 void copy(combo_move_data const& other)
329 {
330 tile = other.tile;
331 tile2 = other.tile2;
332 copy1 = other.copy1;
333 copycnt = other.copycnt;
334 }
335
336 void flip()
337 {
338 int32_t tcnt = tile2-tile+1;
339 int32_t cpy2 = copy1+copycnt-1;
340 zc_swap(tile,copy1);
341 tile2 = cpy2;
342 copycnt = tcnt;
343 }
344 };
345
346 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
347 static optional<ComboMoveUndo> last_combo_move_list;
348 static optional<TileMoveUndo> last_tile_move_list;
349
350 int refl_flags = 0;
351 enum
352 {
353 REFL_90CW, REFL_HFLIP,
354 REFL_90CCW, REFL_VFLIP,
355 REFL_180, REFL_DBLFLIP,
356 REFL_MAX
357 };
358 const char *reflbtn_names[] =
359 {
360 "90 CW", "HFlip",
361 "90 CCW", "VFlip",
362 "180 Rot", "Diag Flip"
363 };
364 int bgmode = 0, xmode = 0;
365 const char *bgmodebtn_names[] =
366 {
367 "BG Color 0", "BG Trans."
368 };
369 const char *xmodebtn_names[] =
370 {
371 "X", "No X"
372 };
373 enum
374 {
375 XMODE_X, XMODE_NOX,
376 XMODE_MAX
377 };
378 enum
379 {
380 BGMODE_0, BGMODE_TRANSP,
381 BGMODE_MAX
382 };
383
384 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
385 {
386 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
387 int32_t size2=size>>1;
388
389 if(newtilebuf[dest_tile].data==NULL)
390 {
391 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
392 }
393
394 int32_t i=0;
395
396 if((dest_tile<<2)+i!=src_quarter1)
397 {
398 for(int32_t j=0; j<8; ++j)
399 {
400 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
401 }
402 }
403
404 i=1;
405
406 if((dest_tile<<2)+i!=src_quarter2)
407 {
408 for(int32_t j=0; j<8; ++j)
409 {
410 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
411 }
412 }
413
414 i=2;
415
416 if((dest_tile<<2)+i!=src_quarter3)
417 {
418 for(int32_t j=0; j<8; ++j)
419 {
420 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
421 }
422 }
423
424 i=3;
425
426 if((dest_tile<<2)+i!=src_quarter4)
427 {
428 for(int32_t j=0; j<8; ++j)
429 {
430 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
431 }
432 }
433 }
434
435 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
436 {
437 al_trace("inside make_combos()\n");
438 int32_t startCombo=0;
439
440 if(!select_combo_2(startCombo,cs))
441 return;
442
443 int32_t temp=combobuf[startCombo].o_tile;
444 combobuf[startCombo].set_tile(startTile);
445
446 if(!edit_combo(startCombo, false, cs))
447 {
448 combobuf[startCombo].set_tile(temp);
449 return;
450 }
451
452 go_combos();
453
454 for(int32_t i=0; i<=endTile-startTile; i++)
455 {
456 combobuf[startCombo+i]=combobuf[startCombo];
457 combobuf[startCombo+i].set_tile(startTile+i);
458 }
459
460 setup_combo_animations();
461 setup_combo_animations2();
462 }
463
464 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
465 {
466 int32_t startCombo=0;
467
468 if(!select_combo_2(startCombo, cs))
469 return;
470
471 int32_t startTile=top*TILES_PER_ROW+left;
472 int32_t temp=combobuf[startCombo].o_tile;
473 combobuf[startCombo].set_tile(startTile);
474
475 if(!edit_combo(startCombo, false, cs))
476 {
477 al_trace("make_combos_rect() early return\n");
478 combobuf[startCombo].set_tile(temp);
479 return;
480 }
481
482 bool smartWrap=false;
483 if(numCols!=4 && numRows>1)
484 {
485 char buf[64];
486 if(numCols<4)
487 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
488 else
489 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
490 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
491 if(ret==1)
492 smartWrap=true;
493 }
494
495 go_combos();
496
497 int32_t combo=startCombo-1;
498 for(int32_t row=0; row<numRows; row++)
499 {
500 for(int32_t col=0; col<numCols; col++)
501 {
502 int32_t tile=startTile+row*TILES_PER_ROW+col;
503 if(smartWrap)
504 // Add 4 per row, and another numRows*4 for every 4 columns
505 // (col&0xFC==col/4*4), and then the column %4
506 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
507 else
508 combo++;
509
510 combobuf[combo]=combobuf[startCombo];
511 combobuf[combo].set_tile(tile);
512 }
513 }
514
515 setup_combo_animations();
516 setup_combo_animations2();
517 }
518
519 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
520
521 static bool nogotiles = false;
522 static bool nogocombos = false;
523
524 void go_tiles()
525 {
526 if(nogotiles) return;
527 last_tile_move_list = nullopt;
528 for(int32_t i=0; i<NEWMAXTILES; ++i)
529 {
530 newundotilebuf[i].format=newtilebuf[i].format;
531
532 if(newundotilebuf[i].data!=NULL)
533 {
534 free(newundotilebuf[i].data);
535 }
536
537 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
538
539 if(newundotilebuf[i].data==NULL)
540 {
541 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
542 }
543
544 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
545 }
546 }
547
548 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
549 {
550 for(int32_t c=0; c<columns; c++)
551 {
552 for(int32_t r=0; r<rows; r++)
553 {
554 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
555 newundotilebuf[t].format=newtilebuf[t].format;
556
557 if(newundotilebuf[t].data!=NULL)
558 {
559 free(newundotilebuf[t].data);
560 }
561
562 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
563
564 if(newundotilebuf[t].data==NULL)
565 {
566 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
567 }
568
569 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
570 }
571 }
572 }
573
574 void comeback_tiles()
575 {
576 if(last_tile_move_list)
577 {
578 last_tile_move_list->undo();
579 last_tile_move_list = nullopt;
580 }
581 for(dword i=0; i<NEWMAXTILES; ++i)
582 {
583 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
584 {
585 newtilebuf[i].format = newundotilebuf[i].format;
586
587 if(newtilebuf[i].data!=NULL)
588 free(newtilebuf[i].data);
589 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
590 if(newtilebuf[i].data==NULL)
591 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
592 }
593
594 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
595 }
596
597 register_blank_tiles();
598 register_used_tiles();
599 }
600
601 void go_combos()
602 {
603 if(nogocombos) return;
604 last_combo_move_list = nullopt;
605
606 undocombobuf = combobuf;
607 }
608
609 void comeback_combos()
610 {
611 if(last_combo_move_list)
612 {
613 last_combo_move_list->undo();
614 last_combo_move_list = nullopt;
615 }
616
617 combobuf = undocombobuf;
618 }
619
620 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
621 {
622 line(dest,x,y,x+s,y+s,c);
623 line(dest,x+s,y,x,y+s,c);
624 }
625 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
626 {
627 line(dest,x,y,x+w,y+h,c);
628 line(dest,x+w,y,x,y+h,c);
629 }
630
631 enum {gm_light, gm_dark, gm_max};
632 int32_t gridmode=gm_light;
633
634 bool has_selection()
635 {
636 for(int32_t i=1; i<17; ++i)
637 {
638 for(int32_t j=1; j<17; ++j)
639 {
640 if(selection_grid[i][j])
641 {
642 return true;
643 }
644 }
645 }
646
647 return false;
648 }
649
650 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
651 {
652 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
653
654 for(int32_t i=1; i<18; ++i)
655 {
656 for(int32_t j=1; j<18; ++j)
657 {
658 // zoomtile16(screen2,tile,79,31,cs,flip,8);
659 if(selection_grid[i-1][j]!=selection_grid[i][j])
660 {
661 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
662 }
663
664 if(selection_grid[i][j-1]!=selection_grid[i][j])
665 {
666 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
667 }
668 }
669 }
670
671 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
672 // selection_anchor=(selection_anchor+1)%64;
673 }
674
675 bool is_selecting()
676 {
677 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
678 }
679
680 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
681 {
682 int32_t x1=zc_min(selecting_x1,selecting_x2);
683 int32_t x2=zc_max(selecting_x1,selecting_x2);
684 int32_t y1=zc_min(selecting_y1,selecting_y2);
685 int32_t y2=zc_max(selecting_y1,selecting_y2);
686
687 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
688 for(int32_t i=1; i<18; ++i)
689 {
690 for(int32_t j=1; j<18; ++j)
691 {
692 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
693
694 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
695 {
696 if(selection_grid[i-1][j]!=selection_grid[i][j])
697 {
698 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
699 }
700
701 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
702 }
703
704 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
705 {
706 if(selection_grid[i][j-1]!=selection_grid[i][j])
707 {
708 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
709 }
710
711 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
712 }
713 }
714 }
715
716 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
717 // selection_anchor=(selection_anchor+1)%64;
718 }
719
720 void unfloat_selection();
721 bool floating_sel = false;
722 byte floatsel[256];
723 byte undofloatsel[256];
724 bool undo_is_floatsel = false;
725
726
727 void add_color_to_selection(int32_t color)
728 {
729 unfloat_selection();
730 for(int32_t i=1; i<17; ++i)
731 {
732 for(int32_t j=1; j<17; ++j)
733 {
734 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
735 {
736 selection_grid[i][j]=1;
737 }
738 }
739 }
740 }
741
742 void remove_color_from_selection(int32_t color)
743 {
744 unfloat_selection();
745 for(int32_t i=1; i<17; ++i)
746 {
747 for(int32_t j=1; j<17; ++j)
748 {
749 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
750 {
751 selection_grid[i][j]=0;
752 }
753 }
754 }
755 }
756
757 void intersect_color_with_selection(int32_t color)
758 {
759 unfloat_selection();
760 for(int32_t i=1; i<17; ++i)
761 {
762 for(int32_t j=1; j<17; ++j)
763 {
764 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
765 {
766 selection_grid[i][j]=1;
767 }
768 else
769 {
770 selection_grid[i][j]=0;
771 }
772 }
773 }
774 }
775
776 bool is_in_selection(int32_t x, int32_t y)
777 {
778 x %= 16; y %= 16;
779 if(x < 0) x = (16 - abs(x));
780 if(y < 0) y = (16 - abs(y));
781 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
782 }
783
784 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
785 {
786 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
787 int gridcol = gridmode==gm_light?vc(7):vc(8);
788
789 cset <<= 4;
790 if(newtilebuf[tile].format>tf4Bit)
791 cset=0;
792
793 int g = hide_grid ? 1 : 0;
794 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
795 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
796
797 unpack_tile(newtilebuf, tile, 0, false);
798 byte *si = unpackbuf;
799 for(int32_t cy=0; cy<16; cy++)
800 {
801 for(int32_t cx=0; cx<16; cx++)
802 {
803 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
804 int32_t dx = ((flip&1)?15-cx:cx)*m;
805 int32_t dy = ((flip&2)?15-cy:cy)*m;
806 if(col)
807 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
808
809 if(!col && xmode == XMODE_X)
810 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
811
812 ++si;
813 }
814 }
815
816 if(!hide_grid)
817 {
818 for(int cx = 0; cx <= 16; ++cx)
819 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
820 for(int cy = 0; cy <= 16; ++cy)
821 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
822 }
823
824 if(show_quartgrid)
825 {
826 int offs = (8*m);
827 const int RAD = 3;
828 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
829 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
830 }
831
832 if(has_selection()||is_selecting())
833 {
834 selection_anchor=(selection_anchor+1)%64;
835
836 if(has_selection()||is_selecting())
837 draw_selection_outline(dest, x, y, m);
838
839 if(is_selecting())
840 draw_selecting_outline(dest, x, y, m);
841 }
842 }
843
844 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
845 {
846 if(!jwin)
847 {
848 if(flags&D_SELECTED)
849 {
850 zc_swap(fg,bg);
851 }
852
853 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
854 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
855 rect(dest,x,y,x+w-2,y+h-2,fg);
856 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
857 }
858 else
859 {
860 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
861 }
862 }
863
864 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
865 {
866 if(!jwin)
867 {
868 if(flags&D_SELECTED)
869 {
870 zc_swap(fg,bg);
871 }
872
873 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
874 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
875 rect(dest,x,y,x+w-2,y+h-2,fg);
876 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
877 }
878 else
879 {
880 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
881 }
882 }
883
884 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
885 {
886 if(flags&D_SELECTED)
887 {
888 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
889 ++x;
890 ++y;
891 --w;
892 --h;
893 }
894 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
895 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
896
897 //Forcibly fit the text within the button
898 char buf[512] = {0};
899 strcpy(buf, text);
900
901 bool dis = (flags&D_DISABLED);
902 auto hei = text_height(font);
903 auto len = text_length(font,buf);
904 auto borderwid = 8;
905 if(len > w - borderwid + (dis ? 1 : 0))
906 {
907 auto ind = strlen(buf) - 1;
908 auto dotcount = 0;
909 while(len > w - borderwid + (dis ? 1 : 0))
910 {
911 if(dotcount >= 2)
912 buf[ind+2] = 0;
913 else ++dotcount;
914 buf[ind--] = '.';
915 len = text_length(font,buf);
916 }
917 }
918 if(dis)
919 {
920 ++len; ++hei;
921 }
922 BITMAP* tmp = create_bitmap_ex(8,len,hei);
923 clear_bitmap(tmp);
924 if(dis)
925 {
926 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
927 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
928 }
929 else
930 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
931 auto tx = x+((w-len)/2);
932 auto ty = y+((h-hei)/2);
933 if(len > w-borderwid)
934 {
935 tx = x+borderwid/2;
936 len = w-borderwid;
937 }
938 if(hei > h-borderwid)
939 {
940 ty = y+borderwid/2;
941 hei = h-borderwid;
942 }
943 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
944 destroy_bitmap(tmp);
945 }
946
947 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
948 {
949 bool over=false;
950
951 while(gui_mouse_b())
952 {
953 //vsync();
954 if(mouse_in_rect(x,y,w,h))
955 {
956 if(!over)
957 {
958 vsync();
959 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
960 over=true;
961
962 update_hw_screen();
963 }
964 }
965 else
966 {
967 if(over)
968 {
969 vsync();
970 draw_layer_button(screen, x, y, w, h, text, flags);
971 over=false;
972
973 update_hw_screen();
974 }
975 }
976 rest(1);
977 }
978
979 if(over)
980 {
981 vsync();
982 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
983
984 update_hw_screen();
985 }
986
987 return over;
988 }
989
990 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
991 {
992 bool over=false;
993
994 while(gui_mouse_b())
995 {
996 custom_vsync();
997
998 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
999 {
1000 if(!over)
1001 {
1002 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1003 over=true;
1004 }
1005 }
1006 else
1007 {
1008 if(over)
1009 {
1010 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1011 over=false;
1012 }
1013 }
1014 }
1015
1016 if(over)
1017 {
1018 custom_vsync();
1019 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1020 }
1021
1022 return over;
1023 }
1024
1025 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1026 {
1027 if(!jwin)
1028 {
1029 if(flags&D_SELECTED)
1030 {
1031 zc_swap(fg,bg);
1032 }
1033
1034 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1035 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1036 rect(dest,x,y,x+w-2,y+h-2,fg);
1037 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1038
1039 if(overlay)
1040 {
1041 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1042 }
1043 else
1044 {
1045 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1046 }
1047 }
1048 else
1049 {
1050 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1051 }
1052 }
1053
1054 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1055 {
1056 bool over=false;
1057
1058 while(gui_mouse_b())
1059 {
1060 custom_vsync();
1061
1062 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1063 {
1064 if(!over)
1065 {
1066 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1067 over=true;
1068 }
1069 }
1070 else
1071 {
1072 if(over)
1073 {
1074 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1075 over=false;
1076 }
1077 }
1078 }
1079
1080 return over;
1081 }
1082
1083 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1084 {
1085 bool over=false;
1086
1087 while(gui_mouse_b())
1088 {
1089 custom_vsync();
1090
1091 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1092 {
1093 if(!over)
1094 {
1095 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1096 over=true;
1097 }
1098 }
1099 else
1100 {
1101 if(over)
1102 {
1103 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1104 over=false;
1105 }
1106 }
1107 }
1108
1109 if(over)
1110 {
1111 custom_vsync();
1112 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1113 }
1114
1115 return over;
1116 }
1117 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1118 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1119
1120 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1121 {
1122 //these are here to bypass compiler warnings about unused arguments
1123 bg=bg;
1124 fg=fg;
1125
1126 int32_t r, center;
1127
1128 for(int32_t k=0; k<7; k++)
1129 {
1130 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1131 {
1132 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1133 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1134 //*
1135 r = 9/2;
1136
1137 center = x+(k*25)+r;
1138 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1139
1140 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1142 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1143 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1144 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1145
1146 if(value==k)
1147 {
1148 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1149 }
1150
1151 //*/
1152 }
1153 }
1154 }
1155
1156 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1157 {
1158 while(gui_mouse_b())
1159 {
1160 custom_vsync();
1161
1162 for(int32_t k=0; k<7; k++)
1163 {
1164 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1165 {
1166 //if on radio button
1167 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1168 {
1169 value=k;
1170 draw_layerradio(dest,x,y,bg,fg,value);
1171 refresh(rMENU);
1172 }
1173 }
1174 }
1175 }
1176 }
1177
1178 //*************** tile flood fill stuff **************
1179
1180 byte tf_c;
1181 byte tf_u;
1182
1183 void tile_floodfill_rec(int32_t x,int32_t y)
1184 {
1185 if(is_in_selection(x,y))
1186 {
1187 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1188 --x;
1189
1190 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1191 {
1192 if(is_in_selection(x,y))
1193 {
1194 unpackbuf[(y<<4)+x] = tf_c;
1195 }
1196
1197 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1198 tile_floodfill_rec(x,y-1);
1199
1200 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1201 tile_floodfill_rec(x,y+1);
1202
1203 ++x;
1204 }
1205 }
1206 }
1207
1208 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1209 {
1210 if(is_in_selection(x,y))
1211 {
1212 if(floating_sel)
1213 {
1214 memcpy(unpackbuf, floatsel, 256);
1215 }
1216 else unpack_tile(newtilebuf, tile, 0, false);
1217 tf_c = c;
1218 tf_u = unpackbuf[(y<<4)+x];
1219
1220 if(tf_u != tf_c)
1221 tile_floodfill_rec(x,y);
1222 if(floating_sel)
1223 {
1224 memcpy(floatsel, unpackbuf, 256);
1225 }
1226 else pack_tile(newtilebuf,unpackbuf,tile);
1227 }
1228 }
1229
1230 //***************** tile editor stuff *****************
1231 12 size_and_pos ok_button(302,562,71,21);
1232 12 size_and_pos cancel_button(376,562,71,21);
1233 12 size_and_pos edit_button(550,562,86,21);
1234 12 size_and_pos hlcbox(742,392,16,16);
1235 12 size_and_pos hov_prev(742,338,50,50);
1236 12 size_and_pos cpalette_4(648,416,4,4,64,64);
1237 12 size_and_pos cpalette_8(648,416,16,14,16,18);
1238 12 size_and_pos fg_prev(648,316,50,50);
1239 12 size_and_pos bg_prev(648+30,316+30,50,50);
1240 12 size_and_pos zoomtile(124,32,16,16,32,32);
1241 12 size_and_pos prev_til_1(648,31,96,96);
1242 12 size_and_pos prev_til_2(752,31,96,96);
1243 12 size_and_pos prev_til_3(648,135,96,96);
1244 12 size_and_pos prev_til_4(752,135,96,96);
1245 12 size_and_pos ref_til(14,189,96,96);
1246 12 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1247 12 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1248 12 size_and_pos color_info(4,294,1,1,116,8);
1249 12 size_and_pos color_info_btn(24,294,96,21);
1250 12 size_and_pos tool_btns(22,29,2,4,39,39);
1251 12 size_and_pos x_btn(890,5,15,13);
1252 12 size_and_pos info_btn(872,5,15,13);
1253 12 size_and_pos hidegrid_cbox(124,552,16,16);
1254 12 size_and_pos quartgrid_cbox(124,572,16,16);
1255 12 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1256 12 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1257 12 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1258
1259 int32_t c1=1;
1260 int32_t c2=0;
1261 int32_t floating_tile = -1;
1262 int32_t tool = t_pen;
1263 int32_t old_tool = -1;
1264 int32_t tool_cur = -1;
1265 int32_t select_mode = 0;
1266 int32_t drawing=0;
1267 int32_t reftile = 0;
1268
1269 bool qgrid_tool(int tool)
1270 {
1271 switch(tool)
1272 {
1273 case t_pen:
1274 case t_fill:
1275 case t_recolor:
1276 case t_wand:
1277 return true;
1278 }
1279 return false;
1280 }
1281
1282 void set_tool_sprite(int tool, int type)
1283 {
1284 int spr = ZQM_NORMAL;
1285 switch(tool)
1286 {
1287 case t_pen: spr = ZQM_SWORD; break;
1288 case t_fill: spr = ZQM_POTION; break;
1289 case t_recolor: spr = ZQM_WAND; break;
1290 case t_eyedropper: spr = ZQM_LENS; break;
1291 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1292 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1293 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1294 }
1295 MouseSprite::set(spr);
1296 }
1297 void update_tool_cursor()
1298 {
1299 int32_t temp_mouse_x=gui_mouse_x();
1300 int32_t temp_mouse_y=gui_mouse_y();
1301
1302 int32_t type=0;
1303
1304 if(has_selection())
1305 {
1306 switch(tool)
1307 {
1308 case t_select:
1309 case t_wand:
1310 type+=select_mode;
1311 break;
1312 }
1313 }
1314
1315 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1316 {
1317 if(tool_cur==-1)
1318 set_tool_sprite(tool,type);
1319
1320 tool_cur=tool;
1321 }
1322 else if(tool_cur != -1)
1323 {
1324 MouseSprite::set(ZQM_NORMAL);
1325 tool_cur = -1;
1326 }
1327 }
1328
1329 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile,bool create_tbar)
1330 {
1331 PALETTE tpal;
1332 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1333 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1334 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1335
1336 if(!create_tbar)
1337 {
1338 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1339 }
1340 else
1341 {
1342 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1343 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1344 }
1345
1346 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1347
1348 clear_to_color(preview_bmp, 0);
1349
1350 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1351 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1352 puttile16(preview_bmp,tile,0,0,cs,flip);
1353 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1354
1355 clear_to_color(preview_bmp, 0);
1356 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1357 overtile16(preview_bmp,tile,0,0,cs,flip);
1358 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1359 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1360
1361 unpack_tile(newtilebuf, tile, 0, true);
1362 if(floating_sel)
1363 for(auto q = 0; q < 256; ++q)
1364 if(floatsel[q])
1365 unpackbuf[q] = floatsel[q];
1366 byte tmptile[256];
1367 byte *tmpptr = tmptile;
1368 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1369 pack_tile(newtilebuf,unpackbuf,tile);
1370 clear_to_color(preview_bmp, 0);
1371
1372 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1373 puttile16(preview_bmp,tile,0,0,cs,flip);
1374 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1375
1376 clear_to_color(preview_bmp, 0);
1377 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1378 overtile16(preview_bmp,tile,0,0,cs,flip);
1379 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1380
1381 if(reftile > 0)
1382 {
1383 clear_to_color(preview_bmp, 0);
1384 jwin_draw_win(screen2, ref_til.x-2,ref_til.y-2, ref_til.w+4, ref_til.h+4, FR_DEEP);
1385 overtile16(preview_bmp,reftile,0,0,cs,flip);
1386 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, ref_til.x, ref_til.y, ref_til.w, ref_til.h);
1387 }
1388
1389 //Color info
1390 {
1391 color_info.h = 1;
1392 if(showcolortip)
1393 {
1394 auto fh = color_info.yscale = text_height(font);
1395 int ty = color_info.y;
1396 if(reftile <= 0)
1397 ty -= ref_til.h + 8;
1398 int y = ty;
1399 int rx = color_info.x+color_info.xscale;
1400 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1401 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1402 auto str = get_tile_colornames(tile,cs);
1403 size_t pos = 0;
1404 char buf[512] = {0};
1405 char cbuf[16] = {0};
1406 while(pos < str.size())
1407 {
1408 y += fh;
1409 if(y+fh > zq_screen_h)
1410 break; //Out of space!
1411 auto endpos = str.find_first_of('\n',pos);
1412
1413 if(endpos == std::string::npos)
1414 {
1415 strcpy(buf,str.substr(pos).c_str());
1416 pos = str.size();
1417 }
1418 else
1419 {
1420 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1421 pos = endpos+1;
1422 }
1423 //Ensure the name fits horizontally
1424 if(text_length(font,buf) > color_info.xscale)
1425 {
1426 size_t pos = 0;
1427 for(; buf[pos]; ++pos)
1428 {
1429 if(buf[pos] == ':')
1430 {
1431 strcpy(cbuf, buf+pos);
1432 buf[pos] = 0;
1433 break;
1434 }
1435 }
1436 size_t clen = text_length(font,cbuf);
1437 size_t dotlen = text_length(font,"..");
1438
1439 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1440 buf[--pos] = 0;
1441 while(buf[pos] == ' ')
1442 buf[pos] = 0;
1443 strcat(buf,"..");
1444 strcat(buf,cbuf);
1445 }
1446 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1447 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1448 ++color_info.h;
1449 }
1450 jwin_draw_frame(screen2,color_info.x-2,ty-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1451 }
1452 else
1453 {
1454 int ty = color_info_btn.y;
1455 if(reftile <= 0)
1456 ty -= ref_til.h + 8;
1457 draw_text_button(screen2,color_info_btn.x,ty,color_info_btn.w,color_info_btn.h,
1458 "Show Colors",vc(1),vc(14),0,true);
1459 }
1460 }
1461
1462 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1463
1464 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1465 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1466
1467 if(floating_sel)
1468 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1469 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1470 if(newtilebuf[tile].format==tf8Bit)
1471 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1472 else
1473 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1474
1475 PALETTE temppal;
1476
1477 //palette and mouse
1478 switch(newtilebuf[tile].format)
1479 {
1480 case tf4Bit:
1481 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1482 get_palette(temppal);
1483
1484 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1485 {
1486 size_and_pos const& s = cpalette_4.subsquare(i);
1487 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1488 }
1489
1490 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1491 break;
1492
1493 case tf8Bit:
1494 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1495
1496 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1497 {
1498 size_and_pos const& s = cpalette_8.subsquare(i);
1499 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1500 }
1501
1502 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1503 break;
1504 }
1505
1506 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1507 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1508 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1509
1510 if(c2==0)
1511 {
1512 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1513 }
1514
1515 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1516 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1517 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1518
1519 if(c1==0)
1520 {
1521 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1522 }
1523
1524 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1525 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1526 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1527 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1528 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1529
1530 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1531 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1532
1533 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1534 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1535
1536 bool qgrd = show_quartgrid && qgrid_tool(tool);
1537 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1538 for(int q = 0; q < REFL_MAX; ++q)
1539 {
1540 auto& sqr = reflbtn_grid.subsquare(q);
1541 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1542 }
1543 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1544 for(int q = 0; q < XMODE_MAX; ++q)
1545 {
1546 auto& sqr = xmodebtn_grid.subsquare(q);
1547 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1548 }
1549 for(int q = 0; q < BGMODE_MAX; ++q)
1550 {
1551 auto& sqr = bgmodebtn_grid.subsquare(q);
1552 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1553 }
1554
1555 //tool buttons
1556 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1557 {
1558 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1559 int col = toolbtn%tool_btns.w;
1560 int row = toolbtn/tool_btns.w;
1561
1562 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1563 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1564 }
1565
1566 //coordinates
1567 {
1568 auto mx = gui_mouse_x();
1569 auto my = gui_mouse_y();
1570 int32_t ind = zoomtile.rectind(mx,my);
1571 int32_t temp_x=ind%zoomtile.w;
1572 int32_t temp_y=ind/zoomtile.w;
1573 int color = -1;
1574
1575 bool is8b = newtilebuf[tile].format > tf4Bit;
1576 if(ind > -1)
1577 {
1578 char xbuf[16];
1579 sprintf(xbuf, "x: %d", temp_x);
1580 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1581 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1582 unpack_tile(newtilebuf, tile, 0, false);
1583 byte *si = unpackbuf;
1584 si+=ind;
1585 color = *si;
1586 }
1587 else if(fg_prev.rect(mx,my))
1588 color = c1;
1589 else if(bg_prev.rect(mx,my))
1590 color = c2;
1591 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1592 if(color > -1)
1593 {
1594 get_palette(tpal);
1595 char separator = ' ';
1596 char buf[512] = {0};
1597
1598 int realcol = color+(is8b?0:CSET(cs));
1599 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1600 auto& c = tpal[realcol];
1601
1602 if(tthighlight)
1603 {
1604 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1605 size_and_pos const& csqr = mainsqr.subsquare(color);
1606
1607 int hlcol = getHighlightColor(tpal[realcol]);
1608 int hlthick = 4;
1609 int extraborder = is8b ? 8 : 0;
1610 int borderthick = hlthick+extraborder;
1611
1612 if(is8b)
1613 {
1614 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1615 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1616 }
1617 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1618 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1619 if(xcolor)
1620 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1621 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1622 }
1623
1624 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1625 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1626
1627 strcpy(buf, get_color_name(realcol, is8b).c_str());
1628 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1629
1630 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1631 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1632
1633 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1634 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1635 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1636 if(xcolor)
1637 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1638 }
1639 }
1640
1641 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1642 update_tool_cursor();
1643 }
1644
1645 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1646 {
1647 unfloat_selection();
1648 if(tile>tile2)
1649 {
1650 zc_swap(tile, tile2);
1651 }
1652
1653 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1654 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1655
1656 int32_t start=tile;
1657 int32_t end=tile2;
1658
1659 // Might have top-right and bottom-left corners selected...
1660 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1661 {
1662 start=tile-(TILECOL(tile)-TILECOL(tile2));
1663 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1664 }
1665
1666 for(int32_t temptile=start; temptile<=end; temptile++)
1667 {
1668 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1669 {
1670 unpack_tile(newtilebuf, temptile, 0, true);
1671
1672 if(flip&1)
1673 {
1674 for(int32_t y=0; y<16; y++)
1675 {
1676 for(int32_t x=0; x<8; x++)
1677 {
1678 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1679 }
1680 }
1681 }
1682
1683 if(flip&2)
1684 {
1685 for(int32_t y=0; y<8; y++)
1686 {
1687 for(int32_t x=0; x<16; x++)
1688 {
1689 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1690 }
1691 }
1692 }
1693
1694 pack_tile(newtilebuf,unpackbuf,temptile);
1695 }
1696 }
1697 }
1698
1699 void rotate_tile(int32_t tile, bool backward)
1700 {
1701 unfloat_selection();
1702 unpack_tile(newtilebuf, tile, 0, true);
1703 byte tempunpackbuf[256];
1704 byte tempx, tempy;
1705
1706 for(tempx=0; tempx<16; tempx++)
1707 {
1708 for(tempy=0; tempy<16; tempy++)
1709 {
1710 if(!backward)
1711 {
1712 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1713 }
1714 else
1715 {
1716 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1717 }
1718 }
1719 }
1720
1721 pack_tile(newtilebuf,tempunpackbuf,tile);
1722 }
1723
1724 static int32_t undocount=128;
1725 byte undotile[256];
1726
1727 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1728 {
1729 byte buf[256];
1730
1731 for(int32_t i=0; i<undocount; i++)
1732 {
1733 newtilebuf[tile].data[i]=undotile[i];
1734 }
1735
1736 if(!(horizontal||vertical))
1737 {
1738 return;
1739 }
1740
1741 unpack_tile(newtilebuf, tile, 0, true);
1742
1743 for(int32_t i=0; i<256; i++)
1744 {
1745 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1746 buf[shift_ind] = unpackbuf[i];
1747 }
1748
1749 if(clear)
1750 {
1751 for(int32_t r=0; r<abs(vertical); r++)
1752 {
1753 for(int32_t c=0; c<16; c++)
1754 {
1755 buf[(vertical>0?r:15-r)*16+c]=0;
1756 }
1757 }
1758
1759 for(int32_t r=0; r<16; r++)
1760 {
1761 for(int32_t c=0; c<abs(horizontal); c++)
1762 {
1763 buf[r*16+(horizontal>0?c:15-c)]=0;
1764 }
1765 }
1766 }
1767
1768 pack_tile(newtilebuf,buf,tile);
1769 }
1770
1771 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1772 {
1773 byte buf[256];
1774
1775 if(!(horizontal||vertical))
1776 {
1777 return;
1778 }
1779
1780 memset(buf,0,256);
1781
1782 for(int32_t i=0; i<256; i++)
1783 {
1784 if(is_in_selection(i%16,i/16))
1785 {
1786 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1787 buf[shift_ind] = floatsel[i];
1788 }
1789 }
1790
1791 memcpy(floatsel,buf,256);
1792 }
1793
1794 void float_selection(int32_t tile, bool clear)
1795 {
1796 if(floating_sel) return;
1797 floating_sel = true;
1798 floating_tile = tile;
1799
1800 unpack_tile(newtilebuf, tile, 0, true);
1801
1802 for(auto q = 0; q < 256; ++q)
1803 {
1804 if(is_in_selection(q%16,q/16))
1805 {
1806 floatsel[q] = unpackbuf[q];
1807 unpackbuf[q] = clear ? 0 : c2;
1808 }
1809 else floatsel[q] = 0;
1810 }
1811
1812 pack_tile(newtilebuf,unpackbuf,tile);
1813 }
1814
1815 void unfloat_selection()
1816 {
1817 if(!floating_sel) return;
1818 floating_sel = false;
1819
1820 unpack_tile(newtilebuf, floating_tile, 0, true);
1821
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(floatsel[q])
1825 {
1826 unpackbuf[q] = floatsel[q];
1827 }
1828 }
1829
1830 pack_tile(newtilebuf,unpackbuf,floating_tile);
1831 floating_tile = -1;
1832 }
1833
1834 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1835 {
1836 if(floating_sel)
1837 {
1838 for(auto q = 0; q < 256; ++q)
1839 {
1840 if(ignore_transparent && floatsel[q]==0)
1841 continue;
1842 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1843 }
1844 return;
1845 }
1846
1847 byte buf[256];
1848 unpack_tile(newtilebuf, tile, 0, true);
1849
1850 for(int32_t i=0; i<256; i++)
1851 {
1852 buf[i]=unpackbuf[i];
1853
1854 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1855 continue;
1856
1857 if(ignore_transparent)
1858 {
1859 if(buf[i]==0)
1860 continue;
1861
1862 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1863 }
1864 else // Don't ignore transparent
1865 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1866 }
1867
1868 pack_tile(newtilebuf,buf,tile);
1869 }
1870
1871 void clear_selection_grid()
1872 {
1873 unfloat_selection();
1874 for(int32_t x=0; x<18; ++x)
1875 {
1876 for(int32_t y=0; y<18; ++y)
1877 {
1878 selection_grid[x][y]=0;
1879 }
1880 }
1881 }
1882
1883 void invert_selection_grid()
1884 {
1885 unfloat_selection();
1886 for(int32_t x=1; x<17; ++x)
1887 {
1888 for(int32_t y=1; y<17; ++y)
1889 {
1890 selection_grid[x][y]=selection_grid[x][y]?0:1;
1891 }
1892 }
1893 }
1894
1895 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1896 {
1897 byte local_grid[16][16];
1898 memset(local_grid, 0, sizeof(local_grid));
1899 for(auto x = 0; x < 16; ++x)
1900 {
1901 for(auto y = 0; y < 16; ++y)
1902 {
1903 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1904 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1905 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1906 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1907 }
1908 }
1909 for(auto x = 0; x < 16; ++x)
1910 {
1911 for(auto y = 0; y < 16; ++y)
1912 {
1913 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1914 }
1915 }
1916 }
1917
1918 void show_edit_tile_help()
1919 {
1920 InfoDialog("Help: Tile Editor", "Hotkeys:"
1921 "\nF1: This Help Dialog"
1922 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1923 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1924 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1925 "\nH/V: Flip | (Shift+)R: Rotate"
1926 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1927 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1928 "\nF12: Screenshot (whole screen)"
1929 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1930 "\nWhen not on Select tools, hold to swap:"
1931 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1932 }
1933
1934 static int move_origin_x=-1, move_origin_y=-1;
1935 static int prev_x=-1, prev_y=-1;
1936 bool __pixel_draw(int x, int y, int tile, int flip)
1937 {
1938 bool ret = false;
1939 switch(tool)
1940 {
1941 case t_pen:
1942 if(flip&1) x=15-x;
1943
1944 if(flip&2) y=15-y;
1945
1946 if(is_in_selection(x,y))
1947 {
1948 if(floating_sel)
1949 {
1950 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1951 }
1952 else
1953 {
1954 unpack_tile(newtilebuf, tile, 0, false);
1955 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1956 pack_tile(newtilebuf, unpackbuf,tile);
1957 }
1958 }
1959 break;
1960
1961 case t_fill:
1962 if(is_in_selection(x,y))
1963 {
1964 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1965 ret = true;
1966 }
1967 break;
1968
1969 case t_recolor:
1970 if(is_in_selection(x,y))
1971 {
1972 if(floating_sel)
1973 {
1974 tf_u = floatsel[(y<<4)+x];
1975 for(int32_t i=0; i<256; i++)
1976 {
1977 if(is_in_selection(i&15,i>>4))
1978 {
1979 if(floatsel[i]==tf_u)
1980 {
1981 floatsel[i]=(drawing==1)?c1:c2;
1982 }
1983 }
1984 }
1985 }
1986 else
1987 {
1988 unpack_tile(newtilebuf, tile, 0, false);
1989 tf_u = unpackbuf[(y<<4)+x];
1990 if(tf_u != ((drawing==1)?c1:c2))
1991 {
1992 for(int32_t i=0; i<256; i++)
1993 {
1994 if(is_in_selection(i&15,i>>4))
1995 {
1996 if(unpackbuf[i]==tf_u)
1997 {
1998 unpackbuf[i]=(drawing==1)?c1:c2;
1999 }
2000 }
2001 }
2002
2003 pack_tile(newtilebuf, unpackbuf,tile);
2004 }
2005 }
2006 ret = true;
2007 }
2008 break;
2009
2010 case t_eyedropper:
2011 if(floating_sel)
2012 memcpy(unpackbuf, floatsel, 256);
2013 else unpack_tile(newtilebuf, tile, 0, false);
2014
2015 if(gui_mouse_b()&1)
2016 {
2017 c1=unpackbuf[((y<<4)+x)];
2018 }
2019
2020 if(gui_mouse_b()&2)
2021 {
2022 c2=unpackbuf[((y<<4)+x)];
2023 }
2024 break;
2025
2026 case t_move:
2027 if((prev_x!=x)||(prev_y!=y))
2028 {
2029 if(has_selection())
2030 {
2031 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2032 wrap_sel_tile(y-prev_y, x-prev_x);
2033 shift_selection_grid(x-prev_x, y-prev_y);
2034 }
2035 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2036 prev_x=x;
2037 prev_y=y;
2038 }
2039 break;
2040
2041 case t_select:
2042 unfloat_selection();
2043 if(flip&1) x=15-x;
2044
2045 if(flip&2) y=15-y;
2046
2047 if(selecting_x1==-1||selecting_y1==-1)
2048 {
2049 selecting_x1=x;
2050 selecting_y1=y;
2051 }
2052 else
2053 {
2054 selecting_x2=x;
2055 selecting_y2=y;
2056 }
2057 break;
2058
2059 case t_wand:
2060 unfloat_selection();
2061 if(flip&1) x=15-x;
2062
2063 if(flip&2) y=15-y;
2064
2065 switch(select_mode)
2066 {
2067 case 0:
2068 clear_selection_grid();
2069 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2070 break;
2071
2072 case 1:
2073 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2074 break;
2075
2076 case 2:
2077 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2078 break;
2079
2080 case 3:
2081 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2082 break;
2083 }
2084
2085 ret = true;
2086 break;
2087 }
2088 return ret;
2089 }
2090 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2091 {
2092 popup_zqdialog_start();
2093 FONT* oldfont = font;
2094 font = get_custom_font(CFONT_DLG);
2095 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2096 status_info.yscale = text_height(font);
2097 status_info.y = 308-(status_info.h*status_info.yscale);
2098 hover_info.yscale = status_info.yscale;
2099 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2100 undocount = tilesize(newtilebuf[tile].format);
2101 clear_selection_grid();
2102 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2103
2104 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2105 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2106
2107 PALETTE tpal;
2108 byte oldtile[256];
2109
2110 memset(&tpal, 0, sizeof(PALETTE));
2111 memset(oldtile, 0, 256);
2112
2113 for(int32_t i=0; i<undocount; i++)
2114 {
2115 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2116 }
2117 byte undoselgrid[16][16];
2118 for(auto x = 0; x < 16; ++x)
2119 for(auto y = 0; y < 16; ++y)
2120 undoselgrid[x][y] = selection_grid[x+1][y+1];
2121 for(auto q = 0; q < 256; ++q)
2122 {
2123 floatsel[q] = 0;
2124 undofloatsel[q] = 0;
2125 floating_sel = false;
2126 undo_is_floatsel = false;
2127 }
2128
2129 int32_t tile_x=-1, tile_y=-1;
2130 int32_t temp_x=-1, temp_y=-1;
2131 bool bdown=false;
2132 int32_t done=0;
2133 drawing=0;
2134 tool_cur = -1;
2135
2136 get_palette(tpal);
2137
2138 if(newtilebuf[tile].format==tf4Bit)
2139 {
2140 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2141 }
2142 else
2143 {
2144 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2145 }
2146
2147 zc_set_palette(tpal);
2148 draw_edit_scr(tile,flip,cs,oldtile, true);
2149
2150 while(gui_mouse_b())
2151 {
2152 /* do nothing */
2153 rest(1);
2154 }
2155
2156 move_origin_x=-1;
2157 move_origin_y=-1;
2158 prev_x=-1;
2159 prev_y=-1;
2160
2161
2162
2163 byte selection_pattern_source[8][8]=
2164 {
2165 {1, 1, 1, 1, 0, 0, 0, 0},
2166 {1, 1, 1, 0, 0, 0, 0, 1},
2167 {1, 1, 0, 0, 0, 0, 1, 1},
2168 {1, 0, 0, 0, 0, 1, 1, 1},
2169 {0, 0, 0, 0, 1, 1, 1, 1},
2170 {0, 0, 0, 1, 1, 1, 1, 0},
2171 {0, 0, 1, 1, 1, 1, 0, 0},
2172 {0, 1, 1, 1, 1, 0, 0, 0},
2173 };
2174
2175 byte selecting_pattern_source[8][8]=
2176 {
2177 {1, 1, 0, 0, 0, 0, 1, 1},
2178 {1, 0, 0, 0, 0, 1, 1, 1},
2179 {0, 0, 0, 0, 1, 1, 1, 1},
2180 {0, 0, 0, 1, 1, 1, 1, 0},
2181 {0, 0, 1, 1, 1, 1, 0, 0},
2182 {0, 1, 1, 1, 1, 0, 0, 0},
2183 {1, 1, 1, 1, 0, 0, 0, 0},
2184 {1, 1, 1, 0, 0, 0, 0, 1},
2185 };
2186
2187 byte intersection_pattern_source[8][8]=
2188 {
2189 {0, 0, 1, 1, 0, 0, 1, 1},
2190 {0, 1, 1, 0, 0, 1, 1, 0},
2191 {1, 1, 0, 0, 1, 1, 0, 0},
2192 {1, 0, 0, 1, 1, 0, 0, 1},
2193 {0, 0, 1, 1, 0, 0, 1, 1},
2194 {0, 1, 1, 0, 0, 1, 1, 0},
2195 {1, 1, 0, 0, 1, 1, 0, 0},
2196 {1, 0, 0, 1, 1, 0, 0, 1},
2197 };
2198
2199 selection_pattern=create_bitmap_ex(8, 8, 8);
2200
2201 for(int32_t x=0; x<8; ++x)
2202 {
2203 for(int32_t y=0; y<8; ++y)
2204 {
2205 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2206 }
2207 }
2208
2209 selecting_pattern=create_bitmap_ex(8, 8, 8);
2210
2211 for(int32_t x=0; x<8; ++x)
2212 {
2213 for(int32_t y=0; y<8; ++y)
2214 {
2215 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2216 }
2217 }
2218
2219 intersection_pattern=create_bitmap_ex(8, 8, 8);
2220
2221 for(int32_t x=0; x<8; ++x)
2222 {
2223 for(int32_t y=0; y<8; ++y)
2224 {
2225 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2226 }
2227 }
2228
2229 do
2230 {
2231 HANDLE_CLOSE_ZQDLG();
2232 if(exiting_program) break;
2233 int32_t temp_mouse_x=gui_mouse_x();
2234 int32_t temp_mouse_y=gui_mouse_y();
2235 rest(4);
2236 bool redraw=false;
2237 bool did_wand_select=false;
2238
2239 if(keypressed())
2240 {
2241 bool ctrl = CHECK_CTRL_CMD;
2242 int k = readkey()>>8;
2243 switch(k)
2244 {
2245 case KEY_F1:
2246 show_edit_tile_help();
2247 break;
2248 case KEY_ENTER_PAD:
2249 case KEY_ENTER:
2250 if(floating_sel)
2251 unfloat_selection();
2252 else done=2;
2253 break;
2254
2255 case KEY_ESC:
2256 if(floating_sel)
2257 unfloat_selection();
2258 else if(has_selection())
2259 clear_selection_grid();
2260 else done=1;
2261 break;
2262
2263 case KEY_DEL:
2264 {
2265 unpack_tile(newtilebuf, tile, 0, false);
2266 bool all = CHECK_CTRL_CMD || !has_selection();
2267 bool canDel = false;
2268 if(all)
2269 {
2270 //Check all
2271 for(auto q = 0; q < 256; ++q)
2272 if(unpackbuf[q])
2273 {
2274 canDel = true;
2275 break;
2276 }
2277 }
2278 else
2279 {
2280 //Check selection
2281 for(auto x = 0; x < 16; ++x)
2282 for(auto y = 0; y < 16; ++y)
2283 if(is_in_selection(x,y))
2284 if(unpackbuf[(y<<4)+x])
2285 {
2286 canDel = true;
2287 break;
2288 }
2289 }
2290 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2291
2292 for(int32_t i=0; i<undocount; i++)
2293 {
2294 undotile[i]=newtilebuf[tile].data[i];
2295 }
2296 for(auto x = 0; x < 16; ++x)
2297 for(auto y = 0; y < 16; ++y)
2298 undoselgrid[x][y] = selection_grid[x+1][y+1];
2299 for(auto q = 0; q < 256; ++q)
2300 undofloatsel[q] = floatsel[q];
2301 undo_is_floatsel = floating_sel;
2302
2303 if(CHECK_CTRL_CMD || !has_selection())
2304 {
2305 //Delete all
2306 for(auto q = 0; q < 256; ++q)
2307 {
2308 unpackbuf[q] = 0;
2309 floatsel[q] = 0;
2310 }
2311 }
2312 else
2313 {
2314 //Delete selection
2315 for(auto x = 0; x < 16; ++x)
2316 for(auto y = 0; y < 16; ++y)
2317 {
2318 if(floating_sel)
2319 {
2320 floatsel[x+(y<<4)] = 0;
2321 }
2322 else if(is_in_selection(x,y))
2323 {
2324 unpackbuf[(y<<4)+x] = 0;
2325 }
2326 }
2327 }
2328 pack_tile(newtilebuf, unpackbuf, tile);
2329 redraw=true;
2330 }
2331 break;
2332
2333 case KEY_A:
2334 clear_selection_grid();
2335 invert_selection_grid();
2336 redraw=true;
2337 break;
2338
2339 case KEY_D:
2340 clear_selection_grid();
2341 redraw=true;
2342 break;
2343
2344 case KEY_I:
2345 invert_selection_grid();
2346 redraw=true;
2347 break;
2348
2349 case KEY_H:
2350 flip^=1;
2351 normalize(tile,tile,0,flip);
2352 flip=0;
2353 redraw=true;
2354 break;
2355
2356 case KEY_V:
2357 flip^=2;
2358 normalize(tile,tile,0,flip);
2359 flip=0;
2360 redraw=true;
2361 break;
2362
2363 case KEY_F12:
2364 onSnapshot();
2365 break;
2366
2367 case KEY_R:
2368 {
2369 //if(CHECK_CTRL_CMD))
2370 // {
2371 //do_recolor(tile); redraw=true; saved=false;
2372 // }
2373 //else
2374 // {
2375 go_tiles();
2376 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2377 redraw=true;
2378 saved=false;
2379 break;
2380 }
2381
2382 case KEY_EQUALS:
2383 case KEY_PLUS_PAD:
2384 {
2385 if(CHECK_CTRL_CMD ||
2386 key[KEY_ALT] || key[KEY_ALTGR])
2387 {
2388 for(int32_t i=0; i<undocount; i++)
2389 undotile[i]=newtilebuf[tile].data[i];
2390 for(auto x = 0; x < 16; ++x)
2391 for(auto y = 0; y < 16; ++y)
2392 undoselgrid[x][y] = selection_grid[x+1][y+1];
2393 for(auto q = 0; q < 256; ++q)
2394 undofloatsel[q] = floatsel[q];
2395 undo_is_floatsel = floating_sel;
2396
2397 if(key[KEY_ALT] || key[KEY_ALTGR])
2398 shift_tile_colors(tile, 16, false);
2399 else
2400 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2401 }
2402 else
2403 cs = (cs<13) ? cs+1:0;
2404
2405 redraw=true;
2406 break;
2407 }
2408
2409 case KEY_MINUS:
2410 case KEY_MINUS_PAD:
2411 {
2412 if(CHECK_CTRL_CMD ||
2413 key[KEY_ALT] || key[KEY_ALTGR])
2414 {
2415 for(int32_t i=0; i<undocount; i++)
2416 undotile[i]=newtilebuf[tile].data[i];
2417 for(auto x = 0; x < 16; ++x)
2418 for(auto y = 0; y < 16; ++y)
2419 undoselgrid[x][y] = selection_grid[x+1][y+1];
2420 for(auto q = 0; q < 256; ++q)
2421 undofloatsel[q] = floatsel[q];
2422 undo_is_floatsel = floating_sel;
2423
2424 if(key[KEY_ALT] || key[KEY_ALTGR])
2425 shift_tile_colors(tile, -16, false);
2426 else
2427 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2428 }
2429 else
2430 cs = (cs>0) ? cs-1:13;
2431
2432 redraw=true;
2433 break;
2434 }
2435
2436 case KEY_SPACE:
2437 gridmode=(gridmode+1)%gm_max;
2438 redraw=true;
2439 break;
2440
2441 case KEY_Z:
2442 if(!ctrl)
2443 break;
2444 //Ctrl+Z == undo
2445 [[fallthrough]];
2446 case KEY_U:
2447 for(int32_t i=0; i<undocount; i++)
2448 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2449
2450 for(auto x = 0; x < 16; ++x)
2451 for(auto y = 0; y < 16; ++y)
2452 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2453
2454 for(auto q = 0; q < 256; ++q)
2455 zc_swap(undofloatsel[q], floatsel[q]);
2456 zc_swap(undo_is_floatsel, floating_sel);
2457
2458 redraw=true;
2459 break;
2460
2461 case KEY_S:
2462 if(CHECK_CTRL_CMD)
2463 {
2464 for(int32_t i=0; i<undocount; i++)
2465 {
2466 undotile[i]=newtilebuf[tile].data[i];
2467 }
2468 for(auto x = 0; x < 16; ++x)
2469 for(auto y = 0; y < 16; ++y)
2470 undoselgrid[x][y] = selection_grid[x+1][y+1];
2471 for(auto q = 0; q < 256; ++q)
2472 undofloatsel[q] = floatsel[q];
2473 undo_is_floatsel = floating_sel;
2474
2475 unpack_tile(newtilebuf, tile, 0, false);
2476
2477 if(has_selection())
2478 {
2479 for(int32_t i=0; i<256; i++)
2480 {
2481 if(!is_in_selection(i%16,i/16))
2482 continue;
2483 if(unpackbuf[i]==c1)
2484 {
2485 unpackbuf[i]=c2;
2486 }
2487 else if(unpackbuf[i]==c2)
2488 {
2489 unpackbuf[i]=c1;
2490 }
2491 if(floating_sel)
2492 {
2493 if(floatsel[i]==c1)
2494 {
2495 floatsel[i]=c2;
2496 }
2497 else if(floatsel[i]==c2)
2498 {
2499 floatsel[i]=c1;
2500 }
2501 }
2502 }
2503 }
2504 else
2505 {
2506 for(int32_t i=0; i<256; i++)
2507 {
2508 if(unpackbuf[i]==c1)
2509 {
2510 unpackbuf[i]=c2;
2511 }
2512 else if(unpackbuf[i]==c2)
2513 {
2514 unpackbuf[i]=c1;
2515 }
2516 }
2517 }
2518
2519 pack_tile(newtilebuf, unpackbuf,tile);
2520 }
2521
2522 zc_swap(c1,c2);
2523 redraw=true;
2524 break;
2525
2526 case KEY_UP:
2527 if(CHECK_CTRL_CMD)
2528 {
2529 unfloat_selection();
2530 tile=zc_max(0,tile-TILES_PER_ROW);
2531 undocount = tilesize(newtilebuf[tile].format);
2532
2533 for(int32_t i=0; i<undocount; i++)
2534 {
2535 undotile[i]=newtilebuf[tile].data[i];
2536 oldtile[i]=undotile[i];
2537 }
2538
2539 redraw=true;
2540 }
2541 else
2542 {
2543 for(int32_t i=0; i<undocount; i++)
2544 {
2545 undotile[i]=newtilebuf[tile].data[i];
2546 }
2547 for(auto x = 0; x < 16; ++x)
2548 for(auto y = 0; y < 16; ++y)
2549 undoselgrid[x][y] = selection_grid[x+1][y+1];
2550 for(auto q = 0; q < 256; ++q)
2551 undofloatsel[q] = floatsel[q];
2552 undo_is_floatsel = floating_sel;
2553 if(has_selection())
2554 {
2555 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2556 wrap_sel_tile(-1, 0);
2557 shift_selection_grid(0, -1);
2558 }
2559 else wrap_tile(tile, -1, 0, false);
2560 redraw=true;
2561 }
2562 break;
2563
2564 case KEY_DOWN:
2565 if(CHECK_CTRL_CMD)
2566 {
2567 unfloat_selection();
2568 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2569 undocount = tilesize(newtilebuf[tile].format);
2570
2571 for(int32_t i=0; i<undocount; i++)
2572 {
2573 undotile[i]=newtilebuf[tile].data[i];
2574 oldtile[i]=undotile[i];
2575 }
2576
2577 redraw=true;
2578 }
2579 else
2580 {
2581 for(int32_t i=0; i<undocount; i++)
2582 {
2583 undotile[i]=newtilebuf[tile].data[i];
2584 }
2585 for(auto x = 0; x < 16; ++x)
2586 for(auto y = 0; y < 16; ++y)
2587 undoselgrid[x][y] = selection_grid[x+1][y+1];
2588 for(auto q = 0; q < 256; ++q)
2589 undofloatsel[q] = floatsel[q];
2590 undo_is_floatsel = floating_sel;
2591 if(has_selection())
2592 {
2593 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2594 wrap_sel_tile(1, 0);
2595 shift_selection_grid(0, 1);
2596 }
2597 else wrap_tile(tile, 1, 0, false);
2598 redraw=true;
2599 }
2600 break;
2601
2602 case KEY_LEFT:
2603 if(CHECK_CTRL_CMD)
2604 {
2605 unfloat_selection();
2606 tile=zc_max(0,tile-1);
2607 undocount = tilesize(newtilebuf[tile].format);
2608
2609 for(int32_t i=0; i<undocount; i++)
2610 {
2611 undotile[i]=newtilebuf[tile].data[i];
2612 oldtile[i]=undotile[i];
2613 }
2614
2615 redraw=true;
2616 }
2617 else
2618 {
2619 for(int32_t i=0; i<undocount; i++)
2620 {
2621 undotile[i]=newtilebuf[tile].data[i];
2622 }
2623 for(auto x = 0; x < 16; ++x)
2624 for(auto y = 0; y < 16; ++y)
2625 undoselgrid[x][y] = selection_grid[x+1][y+1];
2626 for(auto q = 0; q < 256; ++q)
2627 undofloatsel[q] = floatsel[q];
2628 undo_is_floatsel = floating_sel;
2629 if(has_selection())
2630 {
2631 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2632 wrap_sel_tile(0, -1);
2633 shift_selection_grid(-1, 0);
2634 }
2635 else wrap_tile(tile, 0, -1, false);
2636 redraw=true;
2637 }
2638 break;
2639
2640 case KEY_RIGHT:
2641 if(CHECK_CTRL_CMD)
2642 {
2643 unfloat_selection();
2644 tile=zc_min(tile+1, NEWMAXTILES-1);
2645 undocount = tilesize(newtilebuf[tile].format);
2646
2647 for(int32_t i=0; i<undocount; i++)
2648 {
2649 undotile[i]=newtilebuf[tile].data[i];
2650 oldtile[i]=undotile[i];
2651 }
2652
2653 redraw=true;
2654 }
2655 else
2656 {
2657 for(int32_t i=0; i<undocount; i++)
2658 {
2659 undotile[i]=newtilebuf[tile].data[i];
2660 }
2661 for(auto x = 0; x < 16; ++x)
2662 for(auto y = 0; y < 16; ++y)
2663 undoselgrid[x][y] = selection_grid[x+1][y+1];
2664 for(auto q = 0; q < 256; ++q)
2665 undofloatsel[q] = floatsel[q];
2666 undo_is_floatsel = floating_sel;
2667 if(has_selection())
2668 {
2669 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2670 wrap_sel_tile(0, 1);
2671 shift_selection_grid(1, 0);
2672 }
2673 else wrap_tile(tile, 0, 1, false);
2674 redraw=true;
2675 }
2676 break;
2677 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2678 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2679 case KEY_8: case KEY_9:
2680 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2681 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2682 case KEY_8_PAD: case KEY_9_PAD:
2683 {
2684 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2685 if(unsigned(t) < t_max)
2686 {
2687 if(old_tool != -1)
2688 old_tool = t;
2689 else tool = t;
2690 }
2691 break;
2692 }
2693 case KEY_TAB:
2694 {
2695 if(key_shifts & KB_CTRL_CMD_FLAG)
2696 {
2697 xmode = (xmode+1)%XMODE_MAX;
2698 if(!xmode)
2699 bgmode = (bgmode+1)%BGMODE_MAX;
2700 }
2701 else if(key_shifts & KB_SHIFT_FLAG)
2702 hide_grid = !hide_grid;
2703 else show_quartgrid = !show_quartgrid;
2704 redraw = true;
2705 break;
2706 }
2707 }
2708 clear_keybuf();
2709 }
2710
2711 if(!gui_mouse_b())
2712 {
2713 if(is_selecting())
2714 {
2715 unfloat_selection();
2716 int32_t x1=zc_min(selecting_x1,selecting_x2);
2717 int32_t x2=zc_max(selecting_x1,selecting_x2);
2718 int32_t y1=zc_min(selecting_y1,selecting_y2);
2719 int32_t y2=zc_max(selecting_y1,selecting_y2);
2720
2721 if(select_mode==0)
2722 {
2723 clear_selection_grid();
2724 }
2725
2726 for(int32_t x=x1; x<=x2; ++x)
2727 {
2728 for(int32_t y=y1; y<=y2; ++y)
2729 {
2730 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2731 }
2732 }
2733
2734 if(select_mode==3)
2735 {
2736 for(int32_t y=0; y<16; ++y)
2737 {
2738 for(int32_t x=0; x<x1; ++x)
2739 {
2740 selection_grid[x+1][y+1]=0;
2741 }
2742
2743 for(int32_t x=x2+1; x<16; ++x)
2744 {
2745 selection_grid[x+1][y+1]=0;
2746 }
2747 }
2748
2749 for(int32_t x=x1; x<=x2; ++x)
2750 {
2751 for(int32_t y=0; y<y1; ++y)
2752 {
2753 selection_grid[x+1][y+1]=0;
2754 }
2755
2756 for(int32_t y=y2+1; y<16; ++y)
2757 {
2758 selection_grid[x+1][y+1]=0;
2759 }
2760 }
2761 }
2762 }
2763
2764 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2765 did_wand_select=false;
2766 }
2767
2768 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2769 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2770 bool ctrl=CHECK_CTRL_CMD;
2771 static int32_t last_tool_val = 0;
2772
2773 if(tool==t_select||tool==t_wand)
2774 {
2775 if(!drawing)
2776 {
2777 int32_t type=0;
2778
2779 if(has_selection())
2780 {
2781 if(shift)
2782 {
2783 type+=1;
2784 }
2785
2786 if(alt)
2787 {
2788 type+=2;
2789 }
2790 }
2791
2792 if(type!=select_mode)
2793 {
2794 select_mode=type;
2795
2796 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2797 set_tool_sprite(tool,type);
2798 }
2799 }
2800 }
2801 else if(alt||ctrl)
2802 {
2803 if(old_tool==-1)
2804 {
2805 old_tool = tool;
2806 tool_cur = -1;
2807 }
2808 if(alt&&ctrl)
2809 tool = t_recolor;
2810 else if(alt)
2811 tool = t_eyedropper;
2812 else tool = t_fill;
2813 }
2814 else if(old_tool!=-1)
2815 {
2816 tool = old_tool;
2817 old_tool = -1;
2818 tool_cur = -1;
2819 redraw = true;
2820 }
2821 if(last_tool_val != tool)
2822 {
2823 redraw = true;
2824 tool_cur = -1;
2825 update_tool_cursor();
2826 last_tool_val = tool;
2827 }
2828
2829 if(!bdown)
2830 {
2831 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2832 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2833 }
2834
2835 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2836 {
2837 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2838 {
2839 if(tool==t_move || tool==t_fill)
2840 {
2841 set_tool_sprite(tool,1);
2842
2843 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2844 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2845 }
2846
2847 for(int32_t i=0; i<undocount; i++)
2848 {
2849 undotile[i]=newtilebuf[tile].data[i];
2850 }
2851 for(auto x = 0; x < 16; ++x)
2852 for(auto y = 0; y < 16; ++y)
2853 undoselgrid[x][y] = selection_grid[x+1][y+1];
2854 for(auto q = 0; q < 256; ++q)
2855 undofloatsel[q] = floatsel[q];
2856 undo_is_floatsel = floating_sel;
2857
2858 drawing=1;
2859 }
2860
2861 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2862 {
2863 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2864 {
2865 done=2;
2866 }
2867 }
2868
2869 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2870 {
2871 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2872 {
2873 done=1;
2874 }
2875 }
2876
2877 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2878 {
2879 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2880 {
2881 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2882 get_palette(tpal);
2883
2884 if(newtilebuf[tile].format==tf4Bit)
2885 {
2886 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2887 }
2888 else
2889 {
2890 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2891 }
2892
2893 redraw=true;
2894 }
2895 }
2896
2897 int sqr_clicked;
2898 if(show_quartgrid && qgrid_tool(tool))
2899 {
2900 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2901 if(sqr_clicked > -1)
2902 {
2903 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2904 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2905 refl_flags ^= (1<<sqr_clicked);
2906 }
2907 }
2908 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2909 if(sqr_clicked > -1)
2910 {
2911 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2912 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2913 xmode = sqr_clicked;
2914 }
2915 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2916 if(sqr_clicked > -1)
2917 {
2918 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2919 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2920 bgmode = sqr_clicked;
2921 }
2922
2923 if(showcolortip)
2924 {
2925 auto oy = color_info.y;
2926 if(reftile <= 0)
2927 color_info.y -= ref_til.h + 8;
2928 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2929 {
2930 showcolortip = 0;
2931 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2932 }
2933 color_info.y = oy;
2934 }
2935 else
2936 {
2937 auto oy = color_info_btn.y;
2938 if(reftile <= 0)
2939 color_info_btn.y -= ref_til.h + 8;
2940 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2941 {
2942 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2943 {
2944 showcolortip = 1;
2945 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2946 redraw=true;
2947 }
2948 }
2949 color_info_btn.y = oy;
2950 }
2951
2952 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2953 {
2954 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2955 {
2956 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2957 redraw=true;
2958 }
2959 }
2960 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2961 {
2962 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2963 redraw=true;
2964 }
2965 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2966 {
2967 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2968 redraw=true;
2969 }
2970
2971 switch(newtilebuf[tile].format)
2972 {
2973 case tf4Bit:
2974 {
2975 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2976 if(ind > -1)
2977 {
2978 c1 = ind;
2979 redraw=true;
2980 }
2981 break;
2982 }
2983 case tf8Bit:
2984 {
2985 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2986 if(ind > -1)
2987 {
2988 c1 = ind;
2989 redraw=true;
2990 }
2991 break;
2992 }
2993 }
2994
2995
2996 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2997 if(newtool > -1 && newtool < t_max)
2998 {
2999 tool=newtool;
3000 redraw=true;
3001 }
3002
3003 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
3004 {
3005 if(do_x_button(screen, x_btn.x, x_btn.y))
3006 {
3007 done=1;
3008 }
3009 }
3010 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3011 {
3012 if(do_question_button(screen, info_btn.x, info_btn.y))
3013 {
3014 show_edit_tile_help();
3015 }
3016 }
3017
3018 bdown=true;
3019 }
3020
3021 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3022 {
3023 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3024 {
3025 if(tool==t_move || tool==t_fill)
3026 {
3027 set_tool_sprite(tool,1);
3028
3029 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3030 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3031 }
3032
3033 for(int32_t i=0; i<undocount; i++)
3034 {
3035 undotile[i]=newtilebuf[tile].data[i];
3036 }
3037 for(auto x = 0; x < 16; ++x)
3038 for(auto y = 0; y < 16; ++y)
3039 undoselgrid[x][y] = selection_grid[x+1][y+1];
3040 for(auto q = 0; q < 256; ++q)
3041 undofloatsel[q] = floatsel[q];
3042 undo_is_floatsel = floating_sel;
3043
3044 drawing=2;
3045 }
3046
3047 switch(newtilebuf[tile].format)
3048 {
3049 case tf4Bit:
3050 {
3051 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3052 if(ind > -1)
3053 {
3054 c2 = ind;
3055 redraw=true;
3056 }
3057 break;
3058 }
3059 case tf8Bit:
3060 {
3061 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3062 if(ind > -1)
3063 {
3064 c2 = ind;
3065 redraw=true;
3066 }
3067 break;
3068 }
3069 }
3070
3071 bdown=true;
3072 }
3073
3074 if(bdown&&!gui_mouse_b()) //released the buttons
3075 {
3076 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3077 {
3078 if(tool==t_move || tool==t_fill)
3079 {
3080 set_tool_sprite(tool,0);
3081 }
3082 }
3083 }
3084
3085 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3086 {
3087 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3088 int32_t x=ind%zoomtile.w;
3089 int32_t y=ind/zoomtile.w;
3090
3091 bool reset_draw = false;
3092
3093 if(__pixel_draw(x,y,tile,flip))
3094 reset_draw = true;
3095 if(show_quartgrid)
3096 {
3097 auto tmp_sel_mode = select_mode;
3098 if(tool == t_wand && select_mode == 0)
3099 select_mode = 1;
3100 if(qgrid_tool(tool))
3101 {
3102 if(refl_flags & (1<<REFL_HFLIP))
3103 if(__pixel_draw(15-x,y,tile,flip))
3104 reset_draw = true;
3105 if(refl_flags & (1<<REFL_VFLIP))
3106 if(__pixel_draw(x,15-y,tile,flip))
3107 reset_draw = true;
3108 //Diagonal flip and 180° rotation are the same!
3109 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3110 if(__pixel_draw(15-x,15-y,tile,flip))
3111 reset_draw = true;
3112 if(refl_flags & (1<<REFL_90CW))
3113 if(__pixel_draw(15-y,x,tile,flip))
3114 reset_draw = true;
3115 if(refl_flags & (1<<REFL_90CCW))
3116 if(__pixel_draw(y,15-x,tile,flip))
3117 reset_draw = true;
3118 }
3119 select_mode = tmp_sel_mode;
3120 }
3121
3122 if(reset_draw)
3123 drawing = 0;
3124 redraw=true;
3125 }
3126
3127 if(gui_mouse_b()==0)
3128 {
3129 bdown=false;
3130 drawing=0;
3131 }
3132
3133 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3134 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3135
3136 {
3137 tile_x=temp_x;
3138 tile_y=temp_y;
3139 redraw=true;
3140 }
3141
3142 const char *toolnames[t_max]=
3143 {
3144 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3145 };
3146
3147 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3148 if(toolbtn > -1 && toolbtn < t_max)
3149 {
3150 int32_t column = toolbtn%tool_btns.w;
3151 int32_t row = toolbtn/tool_btns.w;
3152
3153 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3154 redraw=true;
3155 }
3156 /* Highlight the hovered pixel? Eh, maybe too much?
3157 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3158 if(hov_pix > -1)
3159 {
3160 int32_t column = hov_pix%zoomtile.w;
3161 int32_t row = hov_pix/zoomtile.w;
3162
3163 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3164 redraw=true;
3165 }*/
3166
3167 if(redraw)
3168 {
3169 draw_edit_scr(tile,flip,cs,oldtile, false);
3170 custom_vsync();
3171 }
3172 else
3173 {
3174 bool hs=has_selection();
3175
3176 if(hs)
3177 {
3178 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3179 }
3180
3181 custom_vsync();
3182
3183 if(hs)
3184 {
3185 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3186 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3187 }
3188
3189 update_tool_cursor();
3190 }
3191
3192 }
3193 while(!done);
3194
3195 unfloat_selection();
3196 clear_selection_grid();
3197
3198 while(gui_mouse_b())
3199 {
3200 /* do nothing */
3201 rest(1);
3202 }
3203
3204 if(done==1)
3205 {
3206 for(int32_t i=0; i<undocount; i++)
3207 {
3208 newtilebuf[tile].data[i]=oldtile[i];
3209 }
3210 }
3211 else
3212 {
3213 byte *buf = new byte[undocount];
3214
3215 // put back old tile
3216 for(int32_t i=0; i<undocount; i++)
3217 {
3218 buf[i] = newtilebuf[tile].data[i];
3219 newtilebuf[tile].data[i] = oldtile[i];
3220 }
3221
3222 // go
3223 go_tiles();
3224
3225 // replace old tile with new one again
3226 for(int32_t i=0; i<undocount; i++)
3227 {
3228 newtilebuf[tile].data[i] = buf[i];
3229 }
3230
3231 saved=false;
3232
3233 if(buf!=NULL)
3234 {
3235 delete[] buf;
3236 }
3237 }
3238
3239 MouseSprite::set(ZQM_NORMAL);
3240 register_blank_tiles();
3241 register_used_tiles();
3242 clear_tooltip();
3243 destroy_bitmap(selection_pattern);
3244 destroy_bitmap(selecting_pattern);
3245 destroy_bitmap(intersection_pattern);
3246 font = oldfont;
3247 popup_zqdialog_end();
3248 }
3249
3250 /* Grab Tile Code */
3251
3252 enum recolorState { rcNone, rc4Bit, rc8Bit };
3253
3254 BITMAP* original_imagebuf_bitmap=NULL;
3255 void *imagebuf=NULL;
3256 int32_t imagebuf_bitmap_scale=0;
3257 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3258 int32_t imagesize=0;
3259 int32_t tilecount=0;
3260 int32_t imagetype=0;
3261 int32_t imagex,imagey,selx,sely;
3262 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3263 bool nesmode=false;
3264 int32_t grabmask=0;
3265 recolorState recolor=rcNone;
3266 PALETTE imagepal;
3267
3268 /* bestfit_color:
3269 * Searches a palette for the color closest to the requested R, G, B value.
3270 */
3271 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3272 {
3273 int32_t bestMatch = 0; // Color with the lowest total difference so far
3274 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3275 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3276
3277 for(int32_t i = 0; i < CSET_SIZE; i++)
3278 {
3279 byte *rgbByte;
3280
3281 // This seems to be right...
3282 if(cs==2 || cs==3 || cs==4)
3283 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3284 else if(cs==9)
3285 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3286 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3287 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3288 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3289 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3290 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3291 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3292 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3293 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3294 else
3295 rgbByte = colordata + (CSET(cs)+i)*3;
3296
3297 int32_t dr=r-*rgbByte;
3298 int32_t dg=g-*(rgbByte+1);
3299 int32_t db=b-*(rgbByte+2);
3300
3301 // Track both the total color difference and the single greatest
3302 // difference of R, G, B. The idea is that it's better to have
3303 // two or three small differences than one big one.
3304 // The differences are multiplied by different numbers to account
3305 // for the differences in perceived brightness of the three colors.
3306 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3307 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3308
3309 // Perfect match? Just stop here.
3310 if(totalDiff==0)
3311 return i;
3312
3313 if(totalDiff < bestTotalDiff || // Best match so far?
3314 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3315 {
3316 bestMatch=i;
3317 bestTotalDiff=totalDiff;
3318 bestHighDiff=highDiff;
3319 }
3320 }
3321
3322 return bestMatch;
3323 }
3324
3325 // Same as the above, but draws from all colors in CSets 0-11.
3326 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3327 {
3328 int32_t bestMatch = 0;
3329 float bestTotalDiff = 100000;
3330 float bestHighDiff = 100000;
3331
3332 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3333 {
3334 byte *rgbByte;
3335
3336 int32_t cs=i>>4;
3337 if(cs==2 || cs==3 || cs==4)
3338 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3339 else if(cs==9)
3340 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3341 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3342 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3343 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3344 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3345 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3346 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3347 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3348 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3349 else
3350 rgbByte = colordata + i * 3;
3351
3352 int32_t dr=r-*rgbByte;
3353 int32_t dg=g-*(rgbByte+1);
3354 int32_t db=b-*(rgbByte+2);
3355
3356 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3357 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3358
3359 if(totalDiff==0) // Perfect match?
3360 return i;
3361
3362 if(totalDiff < bestTotalDiff || // Best match so far?
3363 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3364 {
3365 bestMatch=i;
3366 bestTotalDiff=totalDiff;
3367 bestHighDiff=highDiff;
3368 }
3369 }
3370
3371 return bestMatch;
3372 }
3373
3374 byte cset_reduce_table[PAL_SIZE];
3375
3376 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3377 {
3378 for(int32_t i=0; i<PAL_SIZE; i++)
3379 {
3380 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3381 }
3382 }
3383
3384 void calc_cset_reduce_table_8bit(PALETTE pal)
3385 {
3386 for(int32_t i=0; i<PAL_SIZE; i++)
3387 {
3388 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3389 }
3390 }
3391
3392 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3393 {
3394 //storage space for the grabbed image
3395 byte buf[64];
3396 memset(buf,0,64);
3397 byte *oldsrc=src;
3398
3399 //for 8 lines in the source image...
3400 for(int32_t line=0; line<(nesmode?4:8); line++)
3401 {
3402 //bx is the pixel at the start of a line in the storage buffer
3403 int32_t bx=line<<(nesmode?4:3);
3404 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3405 byte b=src[(bp&1)?line:line<<1];
3406
3407 //fill the storage buffer with data from the source image
3408 for(int32_t i=7; i>=0; --i)
3409 {
3410 buf[bx+i] = (b&1)+(cs<<4);
3411 b>>=1;
3412 }
3413 }
3414
3415 ++src;
3416
3417 for(int32_t p=1; p<bp; p++)
3418 {
3419 for(int32_t line=0; line<(nesmode?4:8); line++)
3420 {
3421 int32_t bx=line<<(nesmode?4:3);
3422 byte b=src[(bp&1)?line:line<<1];
3423
3424 for(int32_t i=7; i>=0; --i)
3425 {
3426 if(nesmode)
3427 {
3428 buf[bx+8+i] = (b&1)+(cs<<4);
3429 }
3430 else
3431 {
3432 buf[bx+i] |= (b&1)<<p;
3433 }
3434
3435 b>>=1;
3436 }
3437 }
3438
3439 if(p&1)
3440 {
3441 src+=15;
3442 }
3443 else
3444 {
3445 ++src;
3446 }
3447 }
3448
3449
3450 if(nesmode)
3451 {
3452 src=oldsrc;
3453
3454 for(int32_t counter=0; counter<2; ++counter, ++src)
3455 {
3456 //for 8 lines in the source image...
3457 for(int32_t line=0; line<4; line++)
3458 {
3459 //bx is the pixel at the start of a line in the storage buffer
3460 int32_t bx=line<<4;
3461 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3462 byte b=src[(line+4)<<1];
3463
3464 //fill the storage buffer with data from the source image
3465 for(int32_t i=7; i>=0; --i)
3466 {
3467 // buf[bx+i] = (b&1)+(cs<<4);
3468 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3469 b>>=1;
3470 }
3471 }
3472 }
3473 }
3474
3475 int32_t c=0;
3476
3477 switch(romtilemode)
3478 {
3479 case 0:
3480 case 1:
3481 case 2:
3482 for(int32_t j=0; j<8; j++)
3483 {
3484 for(int32_t i=0; i<8; i++)
3485 {
3486 putpixel(dest,x+i,y+j,buf[c++]);
3487 }
3488 }
3489
3490 break;
3491
3492 case 3:
3493 for(int32_t j=0; j<4; j++)
3494 {
3495 for(int32_t i=0; i<16; i++)
3496 {
3497 putpixel(dest,x+i,y+j,buf[c++]);
3498 }
3499 }
3500
3501 break;
3502 }
3503 }
3504
3505 const char *file_type[ftMAX]=
3506 {
3507 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3508 };
3509
3510 void draw_grab_window()
3511 {
3512 int w = 640;
3513 int h = 480;
3514 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3515 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3516 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3517 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3518
3519 FONT *oldfont = font;
3520 font = get_zc_font(font_lfont);
3521 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3522 font=oldfont;
3523 }
3524
3525 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3526 {
3527 width=width;
3528 height=height;
3529 white=white; // happy birthday compiler
3530
3531 int32_t yofs=0;
3532 //clear_to_color(screen2,bg);
3533 rectfill(screen2, 0, 0, 319, 159, black);
3534 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3535 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3536 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3537 yofs=3;
3538
3539 // text_mode(-1);
3540 int32_t tileromcolumns=20;
3541
3542 switch(imagetype)
3543 {
3544 case ftBMP:
3545 if(recolor==rcNone)
3546 {
3547 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3548 }
3549 else
3550 {
3551 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3552 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3553
3554 for(int32_t y=0; y<maxy; y++)
3555 {
3556 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3557 {
3558 break;
3559 }
3560
3561 for(int32_t x=0; x<maxx; x++)
3562 {
3563 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3564 {
3565 break;
3566 }
3567
3568 if(recolor==rc8Bit)
3569 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3570 else
3571 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3572 }
3573 }
3574 }
3575
3576 break;
3577
3578 case ftZGP:
3579 case ftQST:
3580 case ftZQT:
3581 case ftQSU:
3582 case ftTIL:
3583 {
3584 tiledata *hold = newtilebuf;
3585 newtilebuf = grabtilebuf;
3586 //fixme
3587 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3588 int32_t t=imagey*TILES_PER_ROW;
3589
3590 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3591 {
3592 if(t <= tilecount)
3593 {
3594 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3595 }
3596
3597 ++t;
3598 }
3599
3600 newtilebuf = hold;
3601 //fixme
3602 }
3603 break;
3604
3605 case ftBIN:
3606 {
3607 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3608 byte *buf = (byte*)imagebuf;
3609
3610 switch(romtilemode)
3611 {
3612 case 0:
3613 for(int32_t y=0; y<160; y+=8)
3614 {
3615 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3616 {
3617 puttileROM(screen2,x,y,buf+ofs,cs);
3618 ofs+=8*bp;
3619 }
3620 }
3621
3622 for(int32_t y=0; y<160; y+=8)
3623 {
3624 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3625 {
3626 puttileROM(screen2,x+128,y,buf+ofs,cs);
3627 ofs+=8*bp;
3628 }
3629 }
3630
3631 break;
3632
3633 case 1:
3634 for(int32_t y=0; y<160; y+=16)
3635 {
3636 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3637 {
3638 puttileROM(screen2,x,y,buf+ofs,cs);
3639 ofs+=8*bp;
3640 puttileROM(screen2,x,y+8,buf+ofs,cs);
3641 ofs+=8*bp;
3642 }
3643 }
3644
3645 for(int32_t y=0; y<160; y+=16)
3646 {
3647 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3648 {
3649 puttileROM(screen2,x+128,y,buf+ofs,cs);
3650 ofs+=8*bp;
3651 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3652 ofs+=8*bp;
3653 }
3654 }
3655
3656 break;
3657
3658 case 2:
3659 for(int32_t y=0; y<160; y+=16)
3660 {
3661 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3662 {
3663 puttileROM(screen2,x,y,buf+ofs,cs);
3664 ofs+=8*bp;
3665 puttileROM(screen2,x+8,y,buf+ofs,cs);
3666 ofs+=8*bp;
3667 puttileROM(screen2,x,y+8,buf+ofs,cs);
3668 ofs+=8*bp;
3669 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3670 ofs+=8*bp;
3671 }
3672 }
3673
3674 for(int32_t y=0; y<160; y+=16)
3675 {
3676 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3677 {
3678 puttileROM(screen2,x+128,y,buf+ofs,cs);
3679 ofs+=8*bp;
3680 puttileROM(screen2,x+136,y,buf+ofs,cs);
3681 ofs+=8*bp;
3682 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3685 ofs+=8*bp;
3686 }
3687 }
3688
3689 break;
3690
3691 case 3:
3692 for(int32_t y=0; y<160; y+=16)
3693 {
3694 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3695 {
3696 puttileROM(screen2,x,y,buf+ofs,cs);
3697 ofs+=8*bp;
3698 puttileROM(screen2,x,y+4,buf+ofs,cs);
3699 ofs+=8*bp;
3700 puttileROM(screen2,x,y+8,buf+ofs,cs);
3701 ofs+=8*bp;
3702 puttileROM(screen2,x,y+12,buf+ofs,cs);
3703 ofs+=8*bp;
3704 }
3705 }
3706
3707 for(int32_t y=0; y<160; y+=16)
3708 {
3709 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3710 {
3711 puttileROM(screen2,x+128,y,buf+ofs,cs);
3712 ofs+=8*bp;
3713 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3714 ofs+=8*bp;
3715 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3716 ofs+=8*bp;
3717 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3718 ofs+=8*bp;
3719 }
3720 }
3721
3722 break;
3723 }
3724 }
3725 break;
3726 }
3727
3728 tiledata hold;
3729 bool holdblank = blank_tile_table[0];
3730
3731 if(is_valid_format(newtilebuf[0].format))
3732 {
3733 hold.format = newtilebuf[0].format;
3734 hold.data = (byte *)malloc(tilesize(hold.format));
3735 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3736 }
3737 else
3738 {
3739 hold.format=tfInvalid;
3740 hold.data=NULL;
3741 }
3742
3743 newtilebuf[0].format=newformat[0];
3744 blank_tile_table[0] = false;
3745
3746 if(newtilebuf[0].data!=NULL)
3747 {
3748 free(newtilebuf[0].data);
3749 }
3750
3751 if(is_valid_format(newtilebuf[0].format))
3752 {
3753 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3754
3755 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3756 {
3757 newtilebuf[0].data[i]=newtile[i];
3758 }
3759 }
3760 else
3761 {
3762 newtilebuf[0].data=NULL;
3763 }
3764
3765 puttile16(screen2,0,208,168+yofs,cs,0);
3766 overtile16(screen2,0,232,168+yofs,cs,0);
3767 newtilebuf[0].format=hold.format;
3768 blank_tile_table[0] = holdblank;
3769
3770 if(newtilebuf[0].data!=NULL)
3771 {
3772 free(newtilebuf[0].data);
3773 }
3774
3775 if(is_valid_format(newtilebuf[0].format))
3776 {
3777 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3778
3779 for(int32_t i=0; i<256; i++)
3780 {
3781 newtilebuf[0].data[i]=hold.data[i];
3782 }
3783 }
3784 else
3785 {
3786 newtilebuf[0].data=NULL;
3787 }
3788
3789 if(hold.data!=NULL)
3790 {
3791 free(hold.data);
3792 }
3793
3794 puttile16(screen2,tile,208,192+yofs,cs,0);
3795 overtile16(screen2,tile,232,192+yofs,cs,0);
3796
3797 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3798 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3799 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3800 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3801
3802 // rect(screen2,183,167,200,184,dvc(7*2));
3803 // rect(screen2,207,167,224,184,dvc(7*2));
3804 // rect(screen2,231,167,248,184,dvc(7*2));
3805 // rect(screen2,207,191,224,208,dvc(7*2));
3806 // rect(screen2,231,191,248,208,dvc(7*2));
3807
3808 /*
3809 rect(screen2,183,167,200,184,vc(14));
3810 rect(screen2,207,167,224,184,vc(14));
3811 rect(screen2,231,167,248,184,vc(14));
3812 rect(screen2,207,191,224,208,vc(14));
3813 rect(screen2,231,191,248,208,vc(14));
3814 */
3815 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3816 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3817 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3818 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3819 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3820 int32_t screen_xofs=6;
3821 int32_t screen_yofs=25;
3822 int winh = 511;
3823 int32_t mul = 2;
3824
3825 yofs=16;
3826
3827 custom_vsync();
3828
3829 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3830
3831 // Suspend the current font while draw_text_button does its work
3832 FONT* oldfont = font;
3833
3834 font = get_zc_font(font_lfont_l);
3835
3836 int txt_x = 8*mul;
3837 int rbtn_x = 255*mul;
3838 int max_fpath_wid = rbtn_x-2-txt_x;
3839 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3840 // Interface
3841 switch(imagetype)
3842 {
3843 case 0:
3844 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3845 break;
3846
3847 case ftBMP:
3848 {
3849 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3850 int text_x = txt_x;
3851 int text_y = (216 + yofs) * mul;
3852 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3853 // int text_w = text_length(font, text.c_str());
3854 // int text_h = text_height(font);
3855 // static int grab_scale_tooltip_id = ttip_register_id();
3856 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3857 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3858
3859 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3860 break;
3861 }
3862
3863 case ftZGP:
3864 case ftQST:
3865 case ftZQT:
3866 case ftQSU:
3867 case ftTIL:
3868 case ftBIN:
3869 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3870 break;
3871 }
3872
3873 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3874 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3875
3876 if(bp==8)
3877 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3878 else
3879 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3880 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3881
3882 if(imagetype==ftBIN)
3883 {
3884 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3885 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3886 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3887 }
3888
3889 int fpath_y = (224+yofs)*mul;
3890 if(text_length(font,imagepath) <= max_fpath_wid)
3891 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3892 else
3893 {
3894 char buf[2052] = {0};
3895 strncpy(buf,imagepath,2048);
3896 int len = strlen(buf);
3897 char *ptr = buf;
3898 char *endptr = buf+len;
3899 char *it = endptr;
3900 int tmpy = fpath_y;
3901 int tmph = text_height(font)+1;
3902 while(true)
3903 {
3904 if(tmpy+tmph > (winh-2))
3905 break; //Out of space!
3906 char c = *it;
3907 bool end = !c;
3908 *it = 0;
3909 int newlen = text_length(font,ptr);
3910 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3911 {
3912 if(end) //No stored character, string ended
3913 {
3914 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3915 break;
3916 }
3917 char t[5];
3918 t[0] = c;
3919 for(int q = 1; q < 5; ++q)
3920 t[q] = it[q];
3921 strcpy(it,"...");
3922 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3923 for(int q = 0; q < 5; ++q)
3924 it[q] = t[q];
3925 tmpy += tmph;
3926 ptr = it;
3927 it = endptr;
3928 }
3929 else
3930 {
3931 *it = c;
3932 --it;
3933 }
3934 }
3935 }
3936 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3937 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3938 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3939 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3940
3941 //int32_t rectw = 16*mul;
3942 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3943 font = oldfont;
3944 }
3945
3946 COLOR_MAP imagepal_table;
3947
3948
3949 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3950 {
3951 //these are here to bypass compiler warnings about unused arguments
3952 x=x;
3953
3954 rgb->r = pal[y].r;
3955 rgb->g = pal[y].g;
3956 rgb->b = pal[y].b;
3957 }
3958
3959
3960 void load_imagebuf()
3961 {
3962 PACKFILE *f;
3963 //cache QRS
3964 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3965 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3966 // {
3967 // cached_rules[q] = quest_rules[q];
3968 // }
3969 bool compressed=false;
3970 bool encrypted=false;
3971 tiledata *hold=newtilebuf;
3972 zquestheader tempheader{};
3973
3974 if(imagebuf)
3975 {
3976 switch(imagetype)
3977 {
3978 case ftBMP:
3979 if (original_imagebuf_bitmap != imagebuf)
3980 destroy_bitmap((BITMAP*)imagebuf);
3981 destroy_bitmap(original_imagebuf_bitmap);
3982 break;
3983
3984 case ftZGP:
3985 case ftQST:
3986 case ftZQT:
3987 case ftQSU:
3988 case ftTIL:
3989 clear_tiles(grabtilebuf);
3990 break;
3991
3992 case ftBIN:
3993 free(imagebuf);
3994 break;
3995 }
3996
3997 imagebuf=NULL;
3998 original_imagebuf_bitmap=NULL;
3999 }
4000
4001 selx=sely=romofs=0;
4002 bp=4;
4003 imagetype=filetype(imagepath);
4004
4005 dword section_id;
4006 word section_version;
4007
4008 switch(imagetype)
4009 {
4010 case ftBMP:
4011 packfile_password("");
4012 memset(imagepal, 0, sizeof(PALETTE));
4013 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4014 imagesize = file_size_ex_password(imagepath,"");
4015 tilecount=0;
4016
4017 RGB_MAP tmp_rgb_table;
4018 create_rgb_table(&tmp_rgb_table, imagepal, NULL);
4019 rgb_map = &tmp_rgb_table;
4020 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4021
4022 if(!original_imagebuf_bitmap)
4023 {
4024 imagetype=0;
4025 }
4026 else
4027 {
4028 imagebuf = original_imagebuf_bitmap;
4029 imagebuf_bitmap_scale = 1;
4030 }
4031
4032 break;
4033
4034 case ftBIN:
4035 packfile_password("");
4036 imagesize = file_size_ex_password(imagepath, "");
4037 tilecount=0;
4038
4039 if(imagesize)
4040 {
4041 imagebuf = malloc(imagesize);
4042
4043 if(!readfile(imagepath,imagebuf,imagesize))
4044 {
4045 free(imagebuf);
4046 imagesize=0;
4047 imagetype=0;
4048 }
4049 }
4050
4051 break;
4052
4053 case ftTIL:
4054 packfile_password("");
4055 imagesize = file_size_ex_password(imagepath,"");
4056 f = pack_fopen_password(imagepath,F_READ,"");
4057
4058 if(!f)
4059 {
4060 goto error;
4061 }
4062
4063 if(!p_mgetl(&section_id,f))
4064 {
4065 goto error;
4066 }
4067
4068 if(section_id==ID_TILES)
4069 {
4070 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4071 {
4072 goto error;
4073 }
4074 }
4075
4076 error:
4077 pack_fclose(f);
4078 tilecount=count_tiles(grabtilebuf);
4079 break;
4080
4081 case ftZGP:
4082 packfile_password("");
4083 imagesize = file_size_ex_password(imagepath, "");
4084 f=pack_fopen_password(imagepath,F_READ,"");
4085
4086 if(!f)
4087 {
4088 goto error2;
4089 }
4090
4091 if(!p_mgetl(&section_id,f))
4092 {
4093 goto error2;
4094 }
4095
4096 if(section_id!=ID_GRAPHICSPACK)
4097 {
4098 goto error2;
4099 }
4100
4101 //section version info
4102 if(!p_igetw(&section_version,f))
4103 {
4104 goto error2;
4105 }
4106
4107 if(!read_deprecated_section_cversion(f))
4108 {
4109 goto error2;
4110 }
4111
4112 //tiles
4113 if(!p_mgetl(&section_id,f))
4114 {
4115 goto error2;
4116 }
4117
4118 if(section_id==ID_TILES)
4119 {
4120 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4121 {
4122 goto error2;
4123 }
4124 }
4125
4126 error2:
4127 pack_fclose(f);
4128 tilecount=count_tiles(grabtilebuf);
4129 break;
4130
4131 case ftQST:
4132 encrypted=true;
4133 case ftZQT:
4134 compressed=true;
4135 case ftQSU:
4136 packfile_password("");
4137 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4138 newtilebuf=grabtilebuf;
4139 byte skip_flags[4];
4140
4141 for(int32_t i=0; i<skip_max; ++i)
4142 {
4143 set_bit(skip_flags,i,1);
4144 }
4145
4146 set_bit(skip_flags,skip_tiles,0);
4147 set_bit(skip_flags,skip_header,0);
4148 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4149 if (ret)
4150 {
4151 imagetype=0;
4152 imagesize=0;
4153 clear_tiles(grabtilebuf);
4154 chop_path(imagepath);
4155 }
4156
4157 if (!ret && encrypted && compressed)
4158 {
4159 if(quest_access(imagepath, &tempheader) != 1)
4160 {
4161 imagetype=0;
4162 imagesize=0;
4163 clear_tiles(grabtilebuf);
4164 chop_path(imagepath);
4165 }
4166 }
4167
4168 //setPackfilePassword(NULL);
4169 newtilebuf=hold;
4170 tilecount=count_tiles(grabtilebuf);
4171 break;
4172 }
4173
4174 rgb_map = zq_rgb_table;
4175 //restore cashed QRs / rules
4176
4177 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4178 // {
4179 // quest_rules[q] = cached_rules[q];
4180 // }
4181 }
4182
4183 static char bitstrbuf[32];
4184 bool leeching_from_tiles=false;
4185
4186 const char *bitlist(int32_t index, int32_t *list_size)
4187 {
4188 int32_t imported=2;
4189
4190 if(index>=0)
4191 {
4192 bound(index,0,leeching_from_tiles?2:1);
4193
4194 if(index==imported)
4195 {
4196 sprintf(bitstrbuf,"Imported");
4197 }
4198 else
4199 {
4200 sprintf(bitstrbuf,"%d",4<<index);
4201 }
4202
4203 return bitstrbuf;
4204 }
4205
4206 *list_size=leeching_from_tiles?3:2;
4207 return NULL;
4208 }
4209
4210 12 static ListData bit_list(bitlist, &font);
4211
4212 static DIALOG leech_dlg[] =
4213 {
4214 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4215 12 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4216 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4217 // 2
4218 12 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4219 12 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4220 12 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4221 // 5
4222 12 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4223 12 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4224 12 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4225 12 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4226 //9
4227 12 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4228 12 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4229
4230 12 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4231 12 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4232 12 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4233 12 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4234 12 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4235 //16
4236 12 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4237 12 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4238 12 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4239
4240 12 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4241 12 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4242 12 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4243
4244 12 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4245 12 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4246 12 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4247
4248 12 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4249 12 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4250 12 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4251
4252 12 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4253 12 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4254 12 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4255 12 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4256 12 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4257 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4258 };
4259
4260 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4261 {
4262 bool shift=true; // fix this!
4263 int32_t cst=0;
4264 int32_t currtile=start;
4265 int32_t height=0, width=0;
4266 byte *testtile = new byte[tilesize(tf32Bit)];
4267 byte imported_format=0;
4268 char updatestring[6];
4269 bool canadd;
4270 bool temp_canadd;
4271 bool duplicate;
4272 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4273 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4274 {
4275 0,0,0,0
4276 };
4277 BITMAP *status;
4278 status = create_bitmap_ex(8,240,140);
4279 clear_bitmap(status);
4280 sprintf(updatestring, "%d", LeechUpdate);
4281 leech_dlg[0].dp2=get_zc_font(font_lfont);
4282 leech_dlg[6].dp=updatestring;
4283
4284 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4285
4286 for(int32_t i=0; i<2; i++)
4287 {
4288 leech_dlg[i+7].flags=0;
4289 }
4290
4291 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4292
4293 for(int32_t i=0; i<12; i++)
4294 {
4295 leech_dlg[i+16].flags=0;
4296 }
4297
4298 for(int32_t i=0; i<4; i++)
4299 {
4300 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4301 }
4302
4303 leech_dlg[31].d1=0;
4304
4305 large_dialog(leech_dlg);
4306
4307 int32_t ret = do_zqdialog(leech_dlg,3);
4308
4309 if(ret==2)
4310 {
4311 delete[] testtile;
4312 return false;
4313 }
4314
4315 int32_t cdepth=leech_dlg[31].d1+1;
4316 int32_t newformat=0;
4317 auto lu = atoi(updatestring);
4318 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4319 if(LeechUpdate!=lu)
4320 {
4321 LeechUpdate=lu;
4322 zc_set_config("zquest","leech_update",LeechUpdate);
4323 }
4324 if(LeechUpdateTiles!=lut)
4325 {
4326 LeechUpdateTiles=lut;
4327 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4328 }
4329
4330 int32_t old_dupe[4];
4331 for(int32_t j=0; j<4; j++)
4332 {
4333 old_dupe[j] = DuplicateAction[j];
4334 for(int32_t i=0; i<3; i++)
4335 {
4336 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4337 {
4338 DuplicateAction[j]=i;
4339 }
4340 }
4341 }
4342 if(old_dupe[0] != DuplicateAction[0])
4343 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4344 if(old_dupe[1] != DuplicateAction[1])
4345 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4346 if(old_dupe[2] != DuplicateAction[2])
4347 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4348 if(old_dupe[3] != DuplicateAction[3])
4349 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4350
4351 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4352 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4353 {
4354 OnlyCheckNewTilesForDuplicates=ocntfd;
4355 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4356 }
4357
4358 leeching_from_tiles=false;
4359
4360 switch(imagetype)
4361 {
4362 case ftBIN:
4363 width=imagesize/128;
4364 height=1;
4365 break;
4366
4367 case ftZGP:
4368 case ftQST:
4369 case ftZQT:
4370 case ftQSU:
4371 case ftTIL:
4372 leeching_from_tiles=true;
4373 width=count_tiles(grabtilebuf);
4374 height=1;
4375 break;
4376
4377 case ftBMP:
4378 width=((((BITMAP*)imagebuf)->w)+15)/16;
4379 height=((((BITMAP*)imagebuf)->h)+15)/16;
4380 break;
4381 }
4382
4383 if(currtile+(width*height)>NEWMAXTILES)
4384 {
4385 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4386 {
4387 delete[] testtile;
4388 return false;
4389 }
4390 }
4391
4392 go_tiles();
4393 saved=false;
4394
4395 for(int32_t ty=0; ty<height; ty++) //for every row
4396 {
4397 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4398 {
4399 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4400 {
4401 FONT *oldfont = font;
4402 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4403 static bool created_tbar=false;
4404 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4405
4406 if(created_tbar)
4407 {
4408 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4409 }
4410 else
4411 {
4412 font = get_zc_font(font_lfont);
4413 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4414 font = oldfont;
4415 created_tbar=true;
4416 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4417 }
4418
4419 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4420 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4421 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4422 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4423 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4424 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4425 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4426 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4427 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4428 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4429 blit(status,screen,0, 0, 40, 20, 240, 140);
4430 }
4431
4432 canadd=true;
4433
4434 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4435 {
4436 delete[] testtile;
4437 return true;
4438 }
4439
4440 switch(imagetype)
4441 {
4442 case ftBIN:
4443 break;
4444
4445 case ftZGP:
4446 case ftQST:
4447 case ftZQT:
4448 case ftQSU:
4449 case ftTIL:
4450 memset(testtile, 0, tilesize(tf32Bit));
4451 imported_format=grabtilebuf[tx].format;
4452
4453 switch(cdepth)
4454 {
4455 case 1: //4-bit
4456 newformat=tf4Bit;
4457
4458 switch(imported_format)
4459 {
4460 case tf4Bit:
4461 case tf8Bit:
4462 for(int32_t y=0; y<16; y++) //snag a tile
4463 {
4464 for(int32_t x=0; x<16; x+=2)
4465 {
4466 testtile[(y*8)+(x/2)]=
4467 (grabtilebuf[tx].data[y*16+x]&15)+
4468 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4469 }
4470 }
4471
4472 break;
4473 }
4474
4475 break;
4476
4477 case 2: //8-bit
4478 newformat=tf8Bit;
4479
4480 switch(imported_format)
4481 {
4482 case tf4Bit:
4483 unpack_tile(grabtilebuf, tx, 0, true);
4484 cst = cs&15;
4485 cst <<= CSET_SHFT;
4486
4487 for(int32_t i=0; i<256; i++)
4488 {
4489 if(!shift||unpackbuf[i]!=0)
4490 {
4491 unpackbuf[i]+=cst;
4492 }
4493 }
4494
4495 pack_tiledata(testtile, unpackbuf, tf8Bit);
4496 break;
4497
4498 case tf8Bit:
4499 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4500 break;
4501 }
4502
4503 break;
4504
4505 case 3: //original tile's bit depth
4506 newformat=imported_format;
4507 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4508 break;
4509 }
4510
4511 break;
4512
4513 case ftBMP:
4514 newformat=cdepth;
4515
4516 for(int32_t y=0; y<16; y++) //snag a tile
4517 {
4518 for(int32_t x=0; x<16; x+=2)
4519 {
4520 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4521 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4522 }
4523 }
4524
4525 break;
4526 }
4527
4528 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4529 {
4530 temp_canadd=true;
4531
4532 //check all tiles before this one
4533 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4534 {
4535 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4536 {
4537 if(DuplicateAction[flipping]>0)
4538 {
4539 if(keypressed())
4540 {
4541 delete[] testtile;
4542 return true;
4543 }
4544
4545 duplicate=(newformat==imported_format);
4546
4547 if(duplicate)
4548 {
4549 switch(flipping)
4550 {
4551 case 0: //normal
4552 if(dest[checktile].data!=NULL)
4553 {
4554 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4555 {
4556 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4557 {
4558 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4559 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4560 {
4561 duplicate=false;
4562 }
4563 }
4564 }
4565 }
4566
4567 break;
4568
4569 case 1: //horizontal
4570 if(dest[checktile].data!=NULL)
4571 {
4572 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4573 {
4574 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4575 {
4576 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4577 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4578 {
4579 duplicate=false;
4580 }
4581 }
4582 }
4583 }
4584
4585 break;
4586
4587 case 2: //vertical
4588 if(dest[checktile].data!=NULL)
4589 {
4590 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4591 {
4592 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4593 {
4594 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4595 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4596 {
4597 duplicate=false;
4598 }
4599 }
4600 }
4601 }
4602
4603 break;
4604
4605 case 3: //both
4606 if(dest[checktile].data!=NULL)
4607 {
4608 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4609 {
4610 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4611 {
4612 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4613 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4614 {
4615 duplicate=false;
4616 }
4617 }
4618 }
4619 }
4620
4621 break;
4622 }
4623 }
4624
4625 if(duplicate==true)
4626 {
4627 ++duplicates_found[flipping];
4628 ++total_duplicates_found;
4629
4630 if(DuplicateAction[flipping]>1)
4631 {
4632 ++total_duplicates_discarded;
4633 temp_canadd=false;
4634 }
4635 }
4636 }
4637
4638 canadd=canadd&&temp_canadd;
4639 }
4640 }
4641 }
4642
4643 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4644 dest[currtile].format=newformat;
4645
4646 if(dest[currtile].data!=NULL)
4647 {
4648 free(dest[currtile].data);
4649 }
4650
4651 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4652
4653 if(dest[currtile].data==NULL)
4654 {
4655 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4656 }
4657
4658 if(canadd==true)
4659 {
4660 /*
4661 for(int32_t y=0; y<16; y++)
4662 {
4663 for(int32_t x=0; x<8; x++)
4664 {
4665 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4666 }
4667 }
4668 */
4669 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4670 ++currtile;
4671 }
4672 }
4673 }
4674
4675 destroy_bitmap(status);
4676 delete[] testtile;
4677 return true;
4678 }
4679
4680 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4681 {
4682 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4683 byte format=defFormat;
4684 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4685
4686 switch(imagetype)
4687 {
4688 case ftZGP:
4689 case ftQST:
4690 case ftZQT:
4691 case ftQSU:
4692 case ftTIL:
4693 case ftBIN:
4694 case ftBMP:
4695 for(int32_t ty=0; ty<height; ty++)
4696 {
4697 for(int32_t tx=0; tx<width; tx++)
4698 {
4699 format=defFormat;
4700 switch(imagetype)
4701 {
4702 case ftZGP:
4703 case ftQST:
4704 case ftZQT:
4705 case ftQSU:
4706 case ftTIL:
4707 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4708 break;
4709 }
4710
4711 bool ever_did_unmasked = false;
4712
4713 for(int32_t y=0; y<16; y++)
4714 {
4715 for(int32_t x=0; x<16; x+=2)
4716 {
4717 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4718 if (masked)
4719 {
4720 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4721 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4722 }
4723 else
4724 {
4725 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4726 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4727 ever_did_unmasked = true;
4728 }
4729 if (format == tf4Bit)
4730 {
4731 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4732 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4733 }
4734 }
4735 }
4736
4737 if (ever_did_unmasked)
4738 newformat[(ty*TILES_PER_ROW)+tx] = format;
4739 }
4740 }
4741
4742 break;
4743
4744 default:
4745 for(int32_t i=0; i<200; i++)
4746 {
4747 for(int32_t j=0; j<256; j++)
4748 {
4749 dest[i][j]=0;
4750 }
4751
4752 newformat[i] = tf4Bit;
4753 }
4754
4755 break;
4756 }
4757 }
4758
4759 static void scale_imagebuf_bitmap()
4760 {
4761 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4762
4763 float scale = IMAGEBUF_SCALE;
4764 int nw = original_imagebuf_bitmap->w * scale;
4765 int nh = original_imagebuf_bitmap->h * scale;
4766 if (nw <= 0 || nh <= 0)
4767 return;
4768
4769 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4770 if (!scaled_bmp)
4771 return;
4772
4773 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4774 if (imagebuf != original_imagebuf_bitmap)
4775 destroy_bitmap((BITMAP*)imagebuf);
4776 imagebuf = scaled_bmp;
4777 }
4778
4779 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4780 void grab_tile(int32_t tile,int32_t &cs)
4781 {
4782 zq_allow_tile_draw_cache = true;
4783
4784 int window_w = 640+6+6, window_h = 480+25+6;
4785 int window_x=(zq_screen_w-window_w)/2;
4786 int window_y=(zq_screen_h-window_h)/2;
4787 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4788 int window_xofs = 0;
4789 int screen_xofs=6;
4790 int screen_yofs=25;
4791 int panel_yofs=0;
4792 int bwidth = 61*1.5;
4793 int bheight = 20*1.5;
4794 int button_x = 255*2;
4795 int grab_ok_button_y = 168*2 + 32;
4796 int leech_button_x = 117*2;
4797 int leech_button_y = 166*2 + 32;
4798 int grab_cancel_button_y = 192*2 + 32;
4799 int file_button_y = 216*2 + 32;
4800 int rec_button_x = 117*2;
4801 int rec_button_y = 192*2 + 32;
4802
4803 int screen_y1 = 24;
4804 int screen_y2 = screen_y1+320-1;
4805
4806 int crect_x = 184+190;
4807 int crect_y = 168*2 + 32;
4808 int crect_w = 8*2;
4809 int crect_h = 8*2;
4810
4811 int xrect_x = 640 + 12 - 21;
4812 int xrect_y = 5;
4813
4814 byte newtile[200][256];
4815 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4816 clear_bitmap(screen3);
4817 byte newformat[200];
4818
4819 memset(newtile, 0, 200*256);
4820 memset(newformat, 0, 200);
4821
4822 static EXT_LIST list[] =
4823 {
4824 { (char *)"All Files (*.*)", NULL },
4825 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4826 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4827 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4828 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4829 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4830 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4831 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4832 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4833 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4834 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4835 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4836 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4837 { NULL, NULL }
4838 };
4839
4840
4841 memset(cset_reduce_table, 0, 256);
4842 memset(col_diff,0,3*128);
4843 bool bdown=false;
4844 int done=0;
4845 int pal=0;
4846 int f=0;
4847 int black=vc(0),white=vc(15);
4848 int selwidth=1, selheight=1;
4849 int selx2=0, sely2=0;
4850 bool xreversed=false, yreversed=false;
4851 bool doleech=false, dofile=false, dopal=false;
4852
4853 int jwin_pal2[jcMAX];
4854 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4855
4856
4857 if(imagebuf==NULL)
4858 load_imagebuf();
4859
4860 calc_cset_reduce_table(imagepal, cs);
4861 calc_cset_reduce_table_8bit(imagepal);
4862 draw_grab_window();
4863 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4864 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4865
4866 while(gui_mouse_b())
4867 {
4868 /* do nothing */
4869 rest(1);
4870 }
4871
4872 do
4873 {
4874 HANDLE_CLOSE_ZQDLG();
4875 if(exiting_program) break;
4876 rest(4);
4877 bool redraw=false;
4878
4879 if(keypressed())
4880 {
4881 redraw=true;
4882
4883 switch(readkey()>>8)
4884 {
4885 case KEY_F:
4886 dofile=true;
4887 break;
4888
4889 case KEY_L:
4890 doleech=true;
4891 break;
4892
4893 case KEY_P:
4894 if(imagetype==ftBMP)
4895 {
4896 dopal=true;
4897 recolor=rcNone;
4898 calc_cset_reduce_table(imagepal, cs);
4899 }
4900
4901 break;
4902
4903 case KEY_ESC:
4904 done=1;
4905 break;
4906
4907 case KEY_ENTER_PAD:
4908 case KEY_ENTER:
4909 done=2;
4910 break;
4911
4912 case KEY_DOWN:
4913 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4914 else ++imagey;
4915
4916 break;
4917
4918 case KEY_UP:
4919 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4920 else --imagey;
4921
4922 break;
4923
4924 case KEY_RIGHT:
4925 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4926 else ++imagex;
4927
4928 break;
4929
4930 case KEY_LEFT:
4931 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4932 else --imagex;
4933
4934 break;
4935
4936 case KEY_PGDN:
4937 imagey+=10;
4938 break;
4939
4940 case KEY_PGUP:
4941 imagey-=10;
4942 break;
4943
4944 case KEY_HOME:
4945 imagex=imagey=0;
4946 break;
4947
4948 case KEY_EQUALS:
4949 case KEY_PLUS_PAD:
4950 cs = (cs<13) ? cs+1:0;
4951 if(recolor==rc4Bit)
4952 calc_cset_reduce_table(imagepal, cs);
4953 break;
4954
4955 case KEY_MINUS:
4956 case KEY_MINUS_PAD:
4957 cs = (cs>0) ? cs-1:13;
4958 if(recolor==rc4Bit)
4959 calc_cset_reduce_table(imagepal, cs);
4960 break;
4961
4962 case KEY_S:
4963 if(grabmode==1) grabmode=8;
4964 else if(grabmode==8) grabmode=16;
4965 else grabmode=1;
4966
4967 break;
4968
4969 case KEY_COMMA:
4970 if (imagetype == ftBMP)
4971 {
4972 imagebuf_bitmap_scale--;
4973 if (imagebuf_bitmap_scale == 0)
4974 imagebuf_bitmap_scale = -2;
4975 scale_imagebuf_bitmap();
4976 }
4977 break;
4978 case KEY_STOP:
4979 if (imagetype == ftBMP)
4980 {
4981 imagebuf_bitmap_scale++;
4982 if (imagebuf_bitmap_scale == -1)
4983 imagebuf_bitmap_scale = 1;
4984 scale_imagebuf_bitmap();
4985 }
4986 break;
4987
4988 case KEY_1:
4989 if(recolor==rc8Bit)
4990 recolor=rcNone;
4991 //imagex=(imagex*bp)>>3;
4992 bp=1;
4993 //imagex<<=3;
4994 nesmode=false;
4995 break;
4996
4997 case KEY_2:
4998 if(recolor==rc8Bit)
4999 recolor=rcNone;
5000 //imagex=(imagex*bp)>>3;
5001 bp=2;
5002 //imagex<<=2;
5003 nesmode=false;
5004 break;
5005
5006 case KEY_N:
5007 if(recolor==rc8Bit)
5008 recolor=rcNone;
5009 //imagex=(imagex*bp)>>3;
5010 bp=2;
5011 //imagex<<=2;
5012 nesmode=true;
5013 break;
5014
5015 case KEY_4:
5016 if(recolor==rc8Bit)
5017 recolor=rcNone;
5018 //imagex=(imagex*bp)>>3;
5019 bp=4;
5020 //imagex<<=1;
5021 nesmode=false;
5022 break;
5023
5024 case KEY_8:
5025 //imagex=(imagex*bp)>>3;
5026 bp=8;
5027 break;
5028
5029 case KEY_B:
5030 if(bp==2&&!nesmode)
5031 {
5032 nesmode=true;
5033 }
5034 else
5035 {
5036 nesmode=false;
5037 bp<<=1;
5038
5039 if(bp==16)
5040 {
5041 bp=1;
5042 //imagex<<=3;
5043 }
5044 else
5045 {
5046 //imagex>>=1;
5047 }
5048 }
5049
5050 break;
5051
5052 case KEY_M:
5053 romtilemode=(romtilemode+1)%4;
5054 break;
5055
5056 case KEY_Z:
5057 if(romofs>0) --romofs;
5058
5059 break;
5060
5061 case KEY_X:
5062 ++romofs;
5063 break;
5064
5065 case KEY_R:
5066 if(pal)
5067 {
5068 dopal=true;
5069 }
5070
5071 if(recolor!=rcNone)
5072 recolor=rcNone;
5073 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5074 {
5075 bp=8;
5076 recolor=rc8Bit;
5077 calc_cset_reduce_table_8bit(imagepal);
5078 }
5079 else
5080 {
5081 if(bp==8)
5082 bp=4;
5083 recolor=rc4Bit;
5084 calc_cset_reduce_table(imagepal, cs);
5085 }
5086 break;
5087
5088 default:
5089 redraw=false;
5090 }
5091
5092 clear_keybuf();
5093
5094 if(imagex<0) imagex=0;
5095
5096 if(imagey<0) imagey=0;
5097
5098 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5099 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5100 }
5101
5102 //boogie!
5103 if(gui_mouse_b()==1 && !bdown)
5104 {
5105 int x=gui_mouse_x();
5106 int y=gui_mouse_y();
5107 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5108 if(do_x_button(screen, xrect_x, xrect_y))
5109 done=1;
5110
5111 if(!bdown)
5112 {
5113 bool regrab=false;
5114 bdown=true;
5115 FONT* oldfont = font;
5116 font = get_zc_font(font_lfont_l);
5117
5118 if(y>=screen_y1 && y<=screen_y2)
5119 {
5120 do
5121 {
5122 HANDLE_CLOSE_ZQDLG();
5123 if(exiting_program) break;
5124 int x = (gui_mouse_x()-screen_xofs) / 2;
5125 int y = (gui_mouse_y()-screen_yofs) / 2;
5126
5127 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5128
5129 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5130 {
5131 selx=vbound((x/grabmode)*grabmode,0,304);
5132 sely=vbound((y/grabmode)*grabmode,0,144);
5133 selx2=selx;
5134 sely2=sely;
5135 selwidth=1;
5136 selheight=1;
5137 xreversed=false;
5138 yreversed=false;
5139 }
5140 else
5141 {
5142 if(xreversed)
5143 {
5144 zc_swap(selx, selx2);
5145 xreversed=false;
5146 }
5147
5148 if(yreversed)
5149 {
5150 zc_swap(sely, sely2);
5151 yreversed=false;
5152 }
5153
5154 selx2=vbound((x/grabmode)*grabmode,0,304);
5155 sely2=vbound((y/grabmode)*grabmode,0,144);
5156 selwidth=1+(abs(selx2-selx))/16;
5157 selheight=1+(abs(sely2-sely))/16;
5158
5159 if(selx2<selx)
5160 {
5161 zc_swap(selx, selx2);
5162 xreversed=true;
5163 }
5164
5165 if(sely2<sely)
5166 {
5167 zc_swap(sely, sely2);
5168 yreversed=true;
5169 }
5170 }
5171
5172 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5173 bool redraw = changed || !(f%8);
5174
5175 if(redraw)
5176 {
5177 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5178 if(changed)
5179 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5180 if(f&8)
5181 {
5182 static const int w = 32;
5183 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5184 }
5185 }
5186 else custom_vsync();
5187
5188 ++f;
5189 }
5190 while(gui_mouse_b());
5191 }
5192 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5193 {
5194 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5195 done=2;
5196 }
5197 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5198 {
5199 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5200 {
5201 doleech=true;
5202 }
5203 }
5204 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5205 {
5206 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5207 done=1;
5208 }
5209 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5210 {
5211 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5212 {
5213 dofile=true;
5214 }
5215 }
5216 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5217 {
5218 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5219 {
5220 if(pal)
5221 {
5222 dopal = true;
5223 }
5224
5225 if(recolor!=rcNone)
5226 recolor=rcNone;
5227 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5228 {
5229 bp=8;
5230 recolor=rc8Bit;
5231 calc_cset_reduce_table_8bit(imagepal);
5232 }
5233 else
5234 {
5235 if(bp==8)
5236 bp=4;
5237 recolor=rc4Bit;
5238 calc_cset_reduce_table(imagepal, cs);
5239 }
5240 redraw=true;
5241 }
5242 }
5243 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5244 {
5245 regrab=true;
5246 grabmask^=1;
5247 }
5248 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5249 {
5250 regrab=true;
5251 grabmask^=2;
5252 }
5253 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5254 {
5255 regrab=true;
5256 grabmask^=4;
5257 }
5258 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5259 {
5260 regrab=true;
5261 grabmask^=8;
5262 }
5263
5264 if(regrab)
5265 {
5266 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5267 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5268 redraw=true;
5269 }
5270
5271 font = oldfont;
5272 }
5273 }
5274
5275 if(gui_mouse_b()==0)
5276 bdown=false;
5277
5278 if(dofile)
5279 {
5280 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5281 {
5282 zc_set_palette(RAMpal);
5283 pal=0;
5284 white=vc(15);
5285 black=vc(0);
5286 strcpy(imagepath,temppath);
5287 load_imagebuf();
5288 imagex=imagey=0;
5289 calc_cset_reduce_table(imagepal, cs);
5290 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5291 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5292 }
5293
5294 while(key[KEY_ESC])
5295 {
5296 poll_keyboard();
5297 /* do nothing */
5298 rest(1);
5299 }
5300
5301 clear_keybuf();
5302 dofile=false;
5303 redraw=true;
5304 }
5305
5306 if(doleech)
5307 {
5308 if(leech_tiles(newtilebuf,tile,cs))
5309 {
5310 done=1;
5311 }
5312 else
5313 {
5314 while(key[KEY_ESC])
5315 {
5316 poll_keyboard();
5317 /* do nothing */
5318 rest(1);
5319 }
5320
5321 clear_keybuf();
5322 redraw=true;
5323 }
5324
5325 doleech=false;
5326 }
5327
5328 if(dopal)
5329 {
5330 pal^=1;
5331
5332 if(pal)
5333 {
5334 get_bw(imagepal,black,white);
5335
5336 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5337 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5338 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5339 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5340 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5341 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5342 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5343 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5344 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5345 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5346 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5347 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5348 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5349 gui_bg_color=jwin_pal[jcBOX];
5350 gui_fg_color=jwin_pal[jcBOXFG];
5351 jwin_set_colors(jwin_pal);
5352 }
5353 else
5354 {
5355 white=vc(15);
5356 black=vc(0);
5357
5358 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5359 gui_bg_color=jwin_pal[jcBOX];
5360 gui_fg_color=jwin_pal[jcBOXFG];
5361 jwin_set_colors(jwin_pal);
5362 }
5363
5364 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5365
5366 dopal=false;
5367 redraw=true;
5368 }
5369
5370 if(redraw)
5371 {
5372 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5373 }
5374 else
5375 {
5376 custom_vsync();
5377 }
5378
5379 if((f%8)==0)
5380 {
5381 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5382
5383 int selxl = selx* 2;
5384 int selyl = sely* 2;
5385 int w = 32;
5386
5387 if(f&8)
5388 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5389
5390 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5391 }
5392
5393 ++f;
5394 }
5395 while(!done);
5396
5397 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5398 gui_bg_color=jwin_pal[jcBOX];
5399 gui_fg_color=jwin_pal[jcBOXFG];
5400 jwin_set_colors(jwin_pal);
5401
5402
5403 if(done==2)
5404 {
5405 go_tiles();
5406 saved=false;
5407
5408 for(int y=0; y<selheight; y++)
5409 {
5410 for(int x=0; x<selwidth; x++)
5411 {
5412 int temptile=tile+((TILES_PER_ROW*y)+x);
5413 int format=(bp==8) ? tf8Bit : tf4Bit;
5414
5415 if(newtilebuf[temptile].data!=NULL)
5416 free(newtilebuf[temptile].data);
5417
5418 newtilebuf[temptile].format=format;
5419 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5420
5421 if(newtilebuf[temptile].data==NULL)
5422 {
5423 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5424 break;
5425 }
5426
5427 for(int i=0; i<256; i++)
5428 {
5429 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5430 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5431 }
5432
5433 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5434 }
5435 }
5436 }
5437
5438 destroy_bitmap(screen3);
5439
5440 if(pal)
5441 zc_set_palette(RAMpal);
5442
5443 recolor=rcNone;
5444 calc_cset_reduce_table(imagepal, cs);
5445 register_blank_tiles();
5446 popup_zqdialog_end();
5447
5448 zq_allow_tile_draw_cache = false;
5449 }
5450
5451 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5452 bool tile_is_used(int32_t tile)
5453 {
5454 return used_tile_table[tile];
5455 }
5456 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5457 {
5458 draw_tiles(screen2, first, cs, f, true);
5459 }
5460 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5461 {
5462 clear_bitmap(dest);
5463 BITMAP *buf = create_bitmap_ex(8,16,16);
5464
5465 int32_t w = 16;
5466 int32_t h = 16;
5467
5468 if(large)
5469 {
5470 w *=2;
5471 h *=2;
5472 }
5473
5474 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5475 {
5476 int32_t x = (i%TILES_PER_ROW)<<4;
5477 int32_t y = (i/TILES_PER_ROW)<<4;
5478 int32_t l = 16;
5479
5480 if(large)
5481 {
5482 x*=2;
5483 y*=2;
5484 l*=2;
5485 }
5486
5487 l-=2;
5488
5489 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5490 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5491 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5492 {
5493 if(!true_empty) //Use pure color 0; no effects
5494 {
5495 if (InvalidBG == 2)
5496 {
5497 draw_checkerboard(dest, x, y, w);
5498 }
5499 else if(InvalidBG == 1)
5500 {
5501 for(int32_t dy=0; dy<=l+1; dy++)
5502 {
5503 for(int32_t dx=0; dx<=l+1; dx++)
5504 {
5505 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5506 }
5507 }
5508 }
5509 else
5510 {
5511 for(int32_t dy=0; dy<=l+1; dy++)
5512 {
5513 for(int32_t dx=0; dx<=l+1; dx++)
5514 {
5515 dest->line[dy+(y)][dx+(x)]=vc(0);
5516 }
5517 }
5518 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5519 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5520 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5521 }
5522 }
5523 }
5524 else
5525 {
5526 puttile16(buf,first+i,0,0,cs,0);
5527 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5528 }
5529
5530 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5531 {
5532 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5533 }
5534 }
5535
5536 destroy_bitmap(buf);
5537 }
5538
5539 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5540 {
5541 int32_t yofs=3;
5542 BITMAP *buf = create_bitmap_ex(8,16,16);
5543 int32_t mul = 2;
5544 FONT *tfont = get_zc_font(font_pfont);
5545
5546 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5547 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5548 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5549 tfont = get_zc_font(font_lfont_l);
5550
5551 // Copied tile and numbers
5552 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5553 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5554 if(copy>=0)
5555 {
5556 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5557 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5558
5559 if(copycnt>1)
5560 {
5561 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5562 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5563 }
5564 else
5565 {
5566 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5567 }
5568 }
5569 else // No tiles copied
5570 {
5571 if (InvalidBG == 2)
5572 {
5573 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5574 }
5575 else if(InvalidBG == 1)
5576 {
5577 for(int32_t dy=0; dy<16*mul; dy++)
5578 {
5579 for(int32_t dx=0; dx<16*mul; dx++)
5580 {
5581 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5582 }
5583 }
5584 }
5585 else
5586 {
5587 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5588 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5589 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5590 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5591 }
5592 }
5593
5594
5595 // Current tile
5596 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5597 puttile16(buf,tile,0,0,cs,0);
5598 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5599
5600 // Current selection mode
5601 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5602 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5603
5604 if(tile>tile2)
5605 {
5606 zc_swap(tile,tile2);
5607 }
5608
5609 char tbuf[8];
5610 tbuf[0]=0;
5611
5612 if(tile2!=tile)
5613 {
5614 sprintf(tbuf,"-%d",tile2);
5615 }
5616
5617 // Current tile and CSet text
5618 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5619 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5620 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5621
5622 FONT *tf = font;
5623 font = tfont;
5624
5625 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5626 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5627 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5628 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5629 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5630
5631 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5632 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5633 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5634 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5635
5636 font = tf;
5637
5638 int32_t w = 640;
5639 int32_t h = 480;
5640 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5641 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5642 int32_t screen_xofs=window_xofs+6;
5643 int32_t screen_yofs=window_yofs+25;
5644
5645 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5646 }
5647
5648 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5649 {
5650 int32_t yofs=3;
5651 BITMAP *buf = create_bitmap_ex(8,16,16);
5652 int32_t mul = 2;
5653 FONT *tfont = get_zc_font(font_pfont);
5654
5655 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5656 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5657 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5658 tfont = get_zc_font(font_lfont_l);
5659
5660 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5661
5662 if(copy>=0)
5663 {
5664 puttile16(buf,copy,0,0,cs,flip);
5665 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5666 }
5667 else
5668 {
5669 if (InvalidBG == 2)
5670 {
5671 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5672 }
5673 else if(InvalidBG == 1)
5674 {
5675 for(int32_t dy=0; dy<16*mul; dy++)
5676 {
5677 for(int32_t dx=0; dx<16*mul; dx++)
5678 {
5679 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5680 }
5681 }
5682 }
5683 else
5684 {
5685 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5686 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5687 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5688 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5689 }
5690 }
5691
5692 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5693 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5694 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5695
5696 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5697 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5698
5699 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5700 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5701
5702 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5703 {
5704 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5705 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5706 }
5707
5708 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5709 puttile16(buf,tile,0,0, cs,
5710 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5711 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5712
5713 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5714 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5715 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5716 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5717
5718 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5719 {
5720 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5721 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5722 }
5723
5724 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5725 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5726 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5727 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5728
5729
5730 int32_t w = 640;
5731 int32_t h = 480;
5732 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5733 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5734 int32_t screen_xofs=window_xofs+6;
5735 int32_t screen_yofs=window_yofs+25;
5736
5737 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5738 }
5739 /*
5740 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5741 {
5742 buf[t].format=format;
5743 if (buf[t].data!=NULL)
5744 {
5745 free(buf[t].data);
5746 }
5747 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5748 if (buf[t].data==NULL)
5749 {
5750 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5751 }
5752 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5753 {
5754 buf[t].data[i]=0;
5755 }
5756 }
5757 */
5758
5759 int32_t hide_used()
5760 {
5761 show_only_unused_tiles ^= 1;
5762 return D_O_K;
5763 }
5764 int32_t hide_unused()
5765 {
5766 show_only_unused_tiles ^= 2;
5767 return D_O_K;
5768 }
5769 int32_t hide_blank()
5770 {
5771 show_only_unused_tiles ^= 4;
5772 return D_O_K;
5773 }
5774 int32_t hide_8bit_marker()
5775 {
5776 show_only_unused_tiles ^= 8;
5777 return D_O_K;
5778 }
5779
5780 enum
5781 {
5782 MENUID_SELTILE_VIEW_HIDE_USED,
5783 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5784 MENUID_SELTILE_VIEW_HIDE_BLANK,
5785 MENUID_SELTILE_VIEW_HIDE_8BIT,
5786 };
5787
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_view_menu
5788 60 {
5789
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5790
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5791
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5792
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5793 };
5794
5795 12 static std::function<void(int)> select_tile_color_depth_cb;
5796
5797 static void set_tile_color_depth_4()
5798 {
5799 select_tile_color_depth_cb(tf4Bit);
5800 }
5801 static void set_tile_color_depth_8()
5802 {
5803 select_tile_color_depth_cb(tf8Bit);
5804 }
5805 enum
5806 {
5807 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5808 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5809 };
5810
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_color_depth_menu
5811 36 {
5812
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5813
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5814 };
5815
5816 //returns the row the tile is in on its page
5817 int32_t tile_page_row(int32_t tile)
5818 {
5819 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5820 }
5821
5822 enum {ti_none, ti_encompass, ti_broken};
5823
5824 //striped check and striped selection
5825 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5826 {
5827 int32_t cmb_first = cmb.o_tile;
5828 int32_t cmb_last = cmb.o_tile;
5829 do
5830 {
5831 cmb_last = cmb.tile;
5832 animate(cmb, true);
5833 }
5834 while(cmb.tile != cmb.o_tile);
5835 reset_combo_animation(cmb);
5836 cmb_first += offset;
5837 cmb_last += offset;
5838
5839 if(cmb_first > selection_last || cmb_last < selection_first)
5840 return ti_none;
5841 if(cmb_first >= selection_first && cmb_last <= selection_last)
5842 return ti_encompass;
5843
5844 do
5845 {
5846 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5847 {
5848 reset_combo_animation(cmb);
5849 return ti_broken; //contained, but non-encompassing.
5850 }
5851 animate(cmb, true);
5852 }
5853 while(cmb.tile != cmb.o_tile);
5854 reset_combo_animation(cmb);
5855 return ti_none;
5856 }
5857 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5858 {
5859 // if selection is before or after check...
5860 if((check_first>selection_last)||(selection_first>check_last))
5861 {
5862 return ti_none;
5863 }
5864
5865 // if selection envelopes check
5866 if((selection_first<=check_first)&&(selection_last>=check_last))
5867 {
5868 return ti_encompass; //encompass
5869 }
5870
5871 //everything else is a break
5872 return ti_broken; //intersect
5873 }
5874
5875
5876
5877 //rectangular check and striped selection
5878 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5879 {
5880 int32_t ret1=-1, ret2=-1;
5881
5882 for(int32_t i=0; i<check_height; ++i)
5883 {
5884 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5885 int32_t check_last=check_first+check_width-1;
5886 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5887
5888 if(ret2==ti_broken)
5889 {
5890 return ti_broken;
5891 }
5892
5893 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5894 }
5895
5896 if(ret1==ti_encompass)
5897 {
5898 if((TILEROW(selection_first)<=check_top) &&
5899 (TILEROW(selection_last)>=(check_top+check_height-1)))
5900 {
5901 return ti_encompass;
5902 }
5903 else
5904 {
5905 return ti_broken;
5906 }
5907 }
5908
5909 return ti_none;
5910 }
5911
5912
5913 //striped check and rectangular selection
5914 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5915 {
5916 if(selection_width < TILES_PER_ROW)
5917 {
5918 int32_t cmb_first = cmb.o_tile;
5919 int32_t cmb_last = cmb.o_tile;
5920 do
5921 {
5922 cmb_last = cmb.tile;
5923 animate(cmb, true);
5924 }
5925 while(cmb.tile != cmb.o_tile);
5926 reset_combo_animation(cmb);
5927 cmb_first += offset;
5928 cmb_last += offset;
5929
5930 if((TILEROW(cmb_first)>=selection_top) &&
5931 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5932 (TILECOL(cmb_first)>=selection_left) &&
5933 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5934 {
5935 return ti_encompass;
5936 }
5937 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5938 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5939 {
5940 return ti_none;
5941 }
5942
5943 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5944 {
5945 int32_t firstcol = TILECOL(cmb_first);
5946 int32_t lastcol = TILECOL(cmb_last);
5947
5948 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5949 return ti_none;
5950 else //handle skip x
5951 {
5952 do
5953 {
5954 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5955 {
5956 reset_combo_animation(cmb);
5957 return ti_broken;
5958 }
5959 animate(cmb, true);
5960 }
5961 while(cmb.tile != cmb.o_tile);
5962 reset_combo_animation(cmb);
5963 return ti_none;
5964 }
5965 }
5966 else //multi-row combo...
5967 {
5968 int32_t row = TILEROW(cmb_first);
5969
5970 do
5971 {
5972 if(row < selection_top || row > selection_top+selection_height-1)
5973 {
5974 //This row isn't in the selection; skip to next row
5975 do
5976 {
5977 animate(cmb,true);
5978 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5979 }
5980 while(TILEROW(cmb.tile) == row);
5981 row = TILEROW(cmb.tile);
5982 continue;
5983 }
5984
5985 //This row IS in the selection; check each tile.
5986 do
5987 {
5988 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5989 {
5990 reset_combo_animation(cmb);
5991 return ti_broken;
5992 }
5993 animate(cmb, true);
5994 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5995 }
5996 while(TILEROW(cmb.tile) == row);
5997 row = TILEROW(cmb.tile);
5998 }
5999 while(cmb.tile != cmb.o_tile);
6000
6001 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
6002 }
6003 }
6004
6005 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6006 }
6007 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6008 {
6009 if(selection_width < TILES_PER_ROW)
6010 {
6011 if((check_last-check_first+1<=selection_width) &&
6012 (TILEROW(check_first)>=selection_top) &&
6013 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6014 (TILECOL(check_first)>=selection_left) &&
6015 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6016 {
6017 return ti_encompass;
6018 }
6019 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6020 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6021 {
6022 return ti_none;
6023 }
6024
6025 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6026
6027 //one last base case: the strip we're interested in only lies along one row
6028 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6029 {
6030 int32_t cfcol = check_first%TILES_PER_ROW;
6031 int32_t clcol = check_last%TILES_PER_ROW;
6032
6033 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6034 return ti_none;
6035 else
6036 return ti_broken;
6037 }
6038 else
6039 {
6040 //recursively cut the strip into substrips which lie entirely on one row
6041 int32_t currow = check_first/TILES_PER_ROW;
6042 int32_t endrow = check_last/TILES_PER_ROW;
6043 int32_t accum = 0;
6044 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6045
6046 for(++currow; currow<endrow; currow++)
6047 {
6048 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6049 }
6050
6051 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6052
6053 if(accum > 0)
6054 return ti_broken;
6055
6056 return ti_none;
6057 }
6058 }
6059
6060 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6061 }
6062
6063 //rectangular check and rectangular selection
6064 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6065 {
6066 if((check_left>=selection_left) &&
6067 (check_left+check_width<=selection_left+selection_width) &&
6068 (check_top>=selection_top) &&
6069 (check_top+check_height<=selection_top+selection_height))
6070 {
6071 return ti_encompass;
6072 }
6073 else
6074 {
6075 for(int32_t i=check_top; i<check_top+check_height; ++i)
6076 {
6077 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6078 {
6079 return ti_broken;
6080 }
6081 }
6082 }
6083
6084 return ti_none;
6085 }
6086
6087
6088
6089
6090 static DIALOG move_textbox_list_dlg[] =
6091 {
6092 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6093 12 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6094 12 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6095 12 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6096 12 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6097 12 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6098 12 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6099 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6100 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6101 };
6102
6103 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6104 {
6105 char buf1[512] = {0};
6106 char buf2[512] = {0};
6107 large_dialog(move_textbox_list_dlg);
6108 DIALOG& tbox = move_textbox_list_dlg[3];
6109 {
6110 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6111 int indx = 0, word_indx = 0;
6112 for(char c : msg)
6113 {
6114 if(c == ' ' || c == '\n')
6115 word_indx = indx;
6116 buf1[indx++] = c;
6117 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6118 {
6119 buf1[word_indx] = 0;
6120 strcpy(buf2, msg.c_str()+word_indx+1);
6121 break;
6122 }
6123 }
6124 }
6125
6126 move_textbox_list_dlg[0].dp = (void*)title;
6127 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6128 move_textbox_list_dlg[1].dp = buf1;
6129 move_textbox_list_dlg[2].dp = buf2;
6130 tbox.dp = textbox;
6131 tbox.d2 = 0;
6132 auto tby = tbox.y;
6133 auto tbh = tbox.h;
6134 if(!buf2[0])
6135 {
6136 auto diff = move_textbox_list_dlg[2].h;
6137 tbox.y -= diff;
6138 tbox.h += diff;
6139 }
6140
6141 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6142 position_mouse_z(0);
6143 tbox.y = tby;
6144 tbox.h = tbh;
6145
6146 return ret == 4;
6147 }
6148
6149 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6150 {
6151 return a==0?b:a==1?c:d;
6152 }
6153
6154 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6155 {
6156 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6157 int i = ti_none;
6158 auto t = ref->getTile() + ref->offset();
6159
6160 if(combo_ref)
6161 {
6162 if(proc.rect)
6163 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6164 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6165 }
6166 else if(proc.rect)
6167 {
6168 if(ref->h > 1)
6169 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6170 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6171 }
6172 else
6173 {
6174 if(ref->h > 1)
6175 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6176 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6177 }
6178
6179 bool in = i != ti_none, out = i != ti_encompass;
6180 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6181 {
6182 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6183 if(proc.rect)
6184 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6185 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6186 if(i != ti_none)
6187 in = true;
6188 if(i != ti_encompass)
6189 out = true;
6190 }
6191 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6192
6193 if(i != ti_none && ref->getTile() != 0)
6194 {
6195 if(mode == Mode::CHECK_ALL)
6196 {
6197 move_refs.emplace_back(std::move(ref));
6198 return true;
6199 }
6200 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6201 {
6202 if(warning_flood || warning_list.tellp() >= 65000)
6203 {
6204 if(!warning_flood)
6205 warning_list << "...\n...\n...\nmany others";
6206 warning_flood = true;
6207 }
6208 else
6209 warning_list << ref->name << '\n';
6210 }
6211 else if(i==ti_encompass)
6212 {
6213 move_refs.emplace_back(std::move(ref));
6214 return true;
6215 }
6216 }
6217 return false;
6218 }
6219
6220 bool TileMoveList::check_prot()
6221 {
6222 if(!TileProtection)
6223 return true;
6224 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6225
6226 warning_flood = false;
6227 warning_list.clear();
6228
6229 return ret;
6230 }
6231
6232 void TileMoveList::add_diff(int diff)
6233 {
6234 for(auto& ref : move_refs)
6235 ref->addTile(diff);
6236 }
6237
6238 //from 'combo.h'
6239 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6240 {
6241 int i = ti_none;
6242 auto c = ref->getCombo();
6243
6244 if(ref->no_move)
6245 processed_combos[c] = true;
6246 else processed_combos[c]; //inserts element if does not exist
6247 i = move_intersection_ss(c, c, proc._first, proc._last);
6248
6249 if(i != ti_none && ref->getCombo() != 0)
6250 {
6251 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6252 {
6253 if(ComboProtection)
6254 {
6255 if(warning_flood || warning_list.tellp() >= 65000)
6256 {
6257 if(!warning_flood)
6258 warning_list << "...\n...\n...\nmany others";
6259 warning_flood = true;
6260 }
6261 else
6262 warning_list << ref->name << '\n';
6263 }
6264 }
6265 else if(i==ti_encompass)
6266 {
6267 move_refs.emplace_back(std::move(ref));
6268 return true;
6269 }
6270 }
6271 return false;
6272 }
6273
6274 bool ComboMoveList::check_prot()
6275 {
6276 if(!ComboProtection)
6277 return true;
6278 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6279 bool subset_header = false;
6280 for(int q = 0; q < 2; ++q)
6281 {
6282 bool is_dest = (q==1);
6283 if(!is_dest && !source_process)
6284 continue;
6285 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6286 for(auto it = subset.begin(); it != subset.end();)
6287 {
6288 auto s = *it;
6289 if(warning_flood || warning_list.tellp() >= 65000)
6290 {
6291 if(!warning_flood)
6292 warning_list << "...\n...\n...\nmany others";
6293 warning_flood = true;
6294 break;
6295 }
6296 set<int> in_set, out_set;
6297 bool no_move = is_dest;
6298 for(int c : *s)
6299 {
6300 int i = move_intersection_ss(c, c, proc._first, proc._last);
6301 if(i != ti_none)
6302 in_set.insert(c);
6303 if(i != ti_encompass)
6304 out_set.insert(c);
6305 if(!no_move)
6306 {
6307 auto it = processed_combos.find(c);
6308 if(it != processed_combos.end() && it->second)
6309 no_move = true;
6310 }
6311 }
6312 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6313 if(i == ti_encompass && !no_move)
6314 {
6315 it = subset.erase(it);
6316 continue;
6317 }
6318 if(i == ti_none)
6319 {
6320 ++it;
6321 continue;
6322 }
6323
6324 if(!subset_header)
6325 {
6326 subset_header = true;
6327 warning_list << "===== Broken Relative Combo Groups =====\n";
6328 }
6329 bool comma = false;
6330 warning_list << "In(";
6331 for(int c : in_set)
6332 {
6333 if(comma)
6334 warning_list << ",";
6335 else comma = true;
6336 warning_list << c;
6337 }
6338 warning_list << "),Out(";
6339 comma = false;
6340 for(int c : out_set)
6341 {
6342 if(comma)
6343 warning_list << ",";
6344 else comma = true;
6345 warning_list << c;
6346 }
6347 warning_list << ")\n";
6348 it = subset.erase(it);
6349 }
6350 }
6351 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6352
6353 processed_combos.clear();
6354 warning_flood = false;
6355 warning_list.clear();
6356
6357 return ret;
6358 }
6359
6360 void ComboMoveList::add_diff(int diff)
6361 {
6362 for(auto& ref : move_refs)
6363 ref->addCombo(diff);
6364 }
6365
6366 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6367 {
6368 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6369 {
6370 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6371 }
6372 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6373 {
6374 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6375 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6376 }
6377 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6378 {
6379 list.add_tile(&w->tile, "McGuffin Piece");
6380 }
6381 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6382 {
6383 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6384 }
6385 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6386 {
6387 if (w->tile == -1)
6388 return;
6389
6390 list.add_tile(&w->tile, "MiniTile");
6391 }
6392 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6393 {
6394 int fr = w->frames ? w->frames : 1;
6395 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6396 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6397 fr = (fr/4_zf).getCeil();
6398
6399 for(auto q = 0; q < 4; ++q)
6400 {
6401 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6402 }
6403 }
6404 }
6405
6406 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6407 {
6408 for(auto q = 0; q < page.contents.size(); ++q)
6409 {
6410 size_t indx = list.move_refs.size();
6411 collect_subscreen_tiles(*page.contents[q], list);
6412 for(; indx < list.move_refs.size(); ++indx)
6413 {
6414 auto& ref = list.move_refs[indx];
6415 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6416 }
6417 }
6418 }
6419
6420 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6421 {
6422 for (auto q = 0; q < subscreen.pages.size(); ++q)
6423 {
6424 size_t indx = list.move_refs.size();
6425 collect_subscreen_tiles(subscreen.pages[q], list);
6426 for(; indx < list.move_refs.size(); ++indx)
6427 {
6428 auto& ref = list.move_refs[indx];
6429 ref->name = fmt::format("Page {} - {}", q, ref->name);
6430 }
6431 }
6432 }
6433
6434 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6435 {
6436 bool BSZ2 = get_qr(qr_BSZELDA);
6437 bool move = source_process.has_value();
6438 TileMoveUndo local_undo;
6439 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6440 auto& vec = storage.vec;
6441 storage.diff = diff;
6442 storage.state = false;
6443
6444 //Combos
6445 {
6446 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6447 dest_process, source_process, mode,
6448 move
6449 ? "The tiles used by the following combos will be partially cleared by the move."
6450 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6451 ));
6452 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6453 {
6454 auto& cmb = combobuf[q];
6455 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6456 : fmt::format(" ({})", cmb.label));
6457 movelist->add_combo(&cmb, lbl);
6458
6459 //type-specific
6460 char const* type_name = ZI.getComboTypeName(cmb.type);
6461 switch(cmb.type)
6462 {
6463 case cSPOTLIGHT:
6464 {
6465 if(!(cmb.usrflags & cflag1))
6466 break;
6467 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6468 break;
6469 }
6470 }
6471 }
6472 if(!every_proc && !movelist->check_prot())
6473 return false;
6474 }
6475 //Items
6476 {
6477 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6478 dest_process, source_process, mode,
6479 move
6480 ? "The tiles used by the following items will be partially cleared by the move."
6481 : "The tiles used by the following items will be partially or completely overwritten by this process."
6482 ));
6483 build_bii_list(false);
6484 for(int32_t u=0; u<MAXITEMS; u++)
6485 {
6486 auto id = bii[u].i;
6487 itemdata& itm = itemsbuf[id];
6488 if(itm.type == itype_bottle)
6489 {
6490 vector<std::tuple<int,int,int>> rects;
6491 auto fr = itm.frames;
6492 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6493 {
6494 bottletype const& bt = QMisc.bottle_types[q];
6495 if(bt.is_blank())
6496 continue;
6497 rects.emplace_back(fr+q*fr, fr, 1);
6498 }
6499 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6500 false, 0, 0, rects);
6501 }
6502 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6503 }
6504 if(!every_proc && !movelist->check_prot())
6505 return false;
6506 }
6507 //Weapon sprites
6508 {
6509 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6510 dest_process, source_process, mode,
6511 move
6512 ? "The tiles used by the following weapons will be partially cleared by the move."
6513 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6514 ));
6515 build_biw_list();
6516
6517 for(int32_t u=0; u<MAXWPNS; u++)
6518 {
6519 bool ignore_frames=false;
6520 int32_t m=0;
6521
6522 auto id = biw[u].i;
6523 auto& wpn = wpnsbuf[id];
6524
6525 switch(biw[u].i)
6526 {
6527 case wSWORD:
6528 case wWSWORD:
6529 case wMSWORD:
6530 case wXSWORD:
6531 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6532 break;
6533
6534 case wSWORDSLASH:
6535 case wWSWORDSLASH:
6536 case wMSWORDSLASH:
6537 case wXSWORDSLASH:
6538 m=4;
6539 break;
6540
6541 case iwMMeter:
6542 m=9;
6543 break;
6544
6545 case wBRANG:
6546 case wMBRANG:
6547 case wFBRANG:
6548 m=BSZ2?1:3;
6549 break;
6550
6551 case wBOOM:
6552 case wSBOOM:
6553 case ewBOOM:
6554 case ewSBOOM:
6555 ignore_frames=true;
6556 m=2;
6557 break;
6558
6559 case wWAND:
6560 m=1;
6561 break;
6562
6563 case wMAGIC:
6564 m=1;
6565 break;
6566
6567 case wARROW:
6568 case wSARROW:
6569 case wGARROW:
6570 case ewARROW:
6571 m=1;
6572 break;
6573
6574 case wHAMMER:
6575 m=8;
6576 break;
6577
6578 case wHSHEAD:
6579 m=1;
6580 break;
6581
6582 case wHSCHAIN_H:
6583 m=1;
6584 break;
6585
6586 case wHSCHAIN_V:
6587 m=1;
6588 break;
6589
6590 case wHSHANDLE:
6591 m=1;
6592 break;
6593
6594 case iwDeath:
6595 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6596 {
6597 ignore_frames = true;
6598 m=BSZ2?4:2;
6599 }
6600 break;
6601
6602 case iwSpawn:
6603 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6604 {
6605 ignore_frames = true;
6606 m=3;
6607 }
6608 break;
6609 }
6610
6611 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6612 1, fmt::format("{} {}", biw[u].s, id));
6613
6614 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6615 //...these can't be updated by a move.
6616 if((u==3)||(u==9))
6617 {
6618 static int32_t impact_tiles[2] = {54,54};
6619 auto& tile = impact_tiles[u==3 ? 0 : 1];
6620 tile = 54; //dummy tile, ensure it's correct
6621 movelist->add_tile(&tile, 2, 1,
6622 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6623 true);
6624 }
6625 }
6626 if(!every_proc && !movelist->check_prot())
6627 return false;
6628 }
6629 //Hero sprites
6630 {
6631 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6632 dest_process, source_process, mode,
6633 move
6634 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6635 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6636 ));
6637 {
6638 int32_t a_style=(zinit.heroAnimationStyle);
6639 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6640 do \
6641 { \
6642 movelist->add_tile(&ref_sprite[spr_tile], \
6643 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6644 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6645 name, false, \
6646 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6647 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6648 } while(false)
6649 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6650
6651 for(int32_t i=0; i<4; ++i)
6652 {
6653 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6654 }
6655
6656 for(int32_t i=0; i<4; ++i)
6657 {
6658 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6659 }
6660
6661 for(int32_t i=0; i<4; ++i)
6662 {
6663 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6664 }
6665
6666 for(int32_t i=0; i<4; ++i)
6667 {
6668 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6669 }
6670
6671 for(int32_t i=0; i<2; ++i)
6672 {
6673 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6674 }
6675
6676 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6677
6678 for(int32_t i=0; i<4; ++i)
6679 {
6680 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6681 }
6682
6683 for(int32_t i=0; i<4; ++i)
6684 {
6685 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6686 }
6687
6688 for(int32_t i=0; i<4; ++i)
6689 {
6690 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6691 }
6692
6693 for(int32_t i=0; i<2; ++i)
6694 {
6695 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6696 }
6697
6698 for(int32_t i=0; i<4; ++i)
6699 {
6700 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6701 }
6702
6703 for(int32_t i=0; i<4; ++i)
6704 {
6705 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6706 }
6707 for(int32_t i=0; i<4; ++i)
6708 {
6709 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6710 }
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6714 }
6715 for(int32_t i=0; i<4; ++i)
6716 {
6717 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6718 }
6719 for(int32_t i=0; i<4; ++i)
6720 {
6721 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6722 }
6723 for(int32_t i=0; i<4; ++i)
6724 {
6725 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6726 }
6727 for(int32_t i=0; i<4; ++i)
6728 {
6729 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6730 }
6731 for(int32_t i=0; i<4; ++i)
6732 {
6733 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6734 }
6735 //69
6736 for(int32_t i=0; i<4; ++i)
6737 {
6738 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6739 }
6740 //73
6741 for(int32_t i=0; i<4; ++i)
6742 {
6743 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6744 }
6745 //77
6746 for(int32_t i=0; i<4; ++i)
6747 {
6748 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6749 }
6750 //81
6751 for(int32_t i=0; i<4; ++i)
6752 {
6753 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6754 }
6755 //85
6756 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6757 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6758 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6759 for(int32_t i=0; i<4; ++i)
6760 {
6761 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6762 }
6763 //91
6764 }
6765 if(!every_proc && !movelist->check_prot())
6766 return false;
6767 }
6768 //Map Styles
6769 {
6770 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6771 dest_process, source_process, mode,
6772 move
6773 ? "The tiles used by the following map styles will be partially cleared by the move."
6774 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6775 ));
6776 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6777 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6778 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6779 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6780 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6781 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6782 if(!every_proc && !movelist->check_prot())
6783 return false;
6784 }
6785 //Game Icons
6786 {
6787 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6788 dest_process, source_process, mode,
6789 move
6790 ? "The tiles used by the following game icons will be partially cleared by the move."
6791 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6792 ));
6793 for(int32_t u=0; u<4; u++)
6794 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6795 if(!every_proc && !movelist->check_prot())
6796 return false;
6797 }
6798 //DMaps
6799 {
6800 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6801 dest_process, source_process, mode,
6802 move
6803 ? "The tiles used by the following dmaps will be partially cleared by the move."
6804 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6805 ));
6806 for(int32_t u=0; u<MAXDMAPS; u++)
6807 {
6808 auto& dm = DMaps[u];
6809 movelist->add_tile(&dm.minimap_tile[0], 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6810 movelist->add_tile(&dm.minimap_tile[1], 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6811 movelist->add_tile(&dm.largemap_tile[0], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6812 movelist->add_tile(&dm.largemap_tile[1], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6813 }
6814 if(!every_proc && !movelist->check_prot())
6815 return false;
6816 }
6817 //Enemies
6818 {
6819 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6820 dest_process, source_process, mode,
6821 move
6822 ? "The tiles used by the following enemies will be partially cleared by the move."
6823 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6824 ));
6825 build_bie_list(false);
6826 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6827 for(int u=0; u<eMAXGUYS; u++)
6828 {
6829 guydata& enemy=guysbuf[bie[u].i];
6830 bool darknut=false;
6831 bool gleeok=false;
6832
6833 if(enemy.type==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6834 darknut=true;
6835 else if(enemy.type==eeGLEEOK)
6836 gleeok=true;
6837 else if (enemy.type == eePATRA)
6838 {
6839 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6840 {
6841 darknut=true; //uses the same logic no need for separate variables!
6842 }
6843 }
6844
6845 // Dummied out enemies
6846 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6847 {
6848 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6849 {
6850 continue;
6851 }
6852 }
6853
6854 if(newtiles)
6855 {
6856 if(enemy.e_tile==0)
6857 {
6858 continue;
6859 }
6860
6861 vector<std::tuple<int,int,int>> rects;
6862
6863 if(darknut) //or anything that uses S. Tile for with new tiles
6864 {
6865 if (enemy.s_tile != 0)
6866 {
6867 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6868 }
6869 }
6870 else if (gleeok)
6871 {
6872 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6873 {
6874 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6875 }
6876 rects.emplace_back(enemy.attributes[7], 4, 1);
6877 rects.emplace_back(enemy.attributes[8], 4, 1);
6878 }
6879 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6880 false, 0, 0, rects);
6881
6882 }
6883 else
6884 {
6885 if(enemy.tile==0)
6886 {
6887 continue;
6888 }
6889 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6890
6891 if(enemy.s_tile!=0)
6892 {
6893 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6894 }
6895 }
6896 }
6897 if(!every_proc && !movelist->check_prot())
6898 return false;
6899 }
6900 //Subscreens
6901 {
6902 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6903 dest_process, source_process, mode,
6904 move
6905 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6906 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6907 ));
6908
6909 for(auto q = 0; q < subscreens_active.size(); ++q)
6910 {
6911 size_t indx = movelist->move_refs.size();
6912 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6913 for(; indx < movelist->move_refs.size(); ++indx)
6914 {
6915 auto& ref = movelist->move_refs[indx];
6916 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6917 }
6918 }
6919 for(auto q = 0; q < subscreens_passive.size(); ++q)
6920 {
6921 size_t indx = movelist->move_refs.size();
6922 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6923 for(; indx < movelist->move_refs.size(); ++indx)
6924 {
6925 auto& ref = movelist->move_refs[indx];
6926 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6927 }
6928 }
6929 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6930 {
6931 size_t indx = movelist->move_refs.size();
6932 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6933 for(; indx < movelist->move_refs.size(); ++indx)
6934 {
6935 auto& ref = movelist->move_refs[indx];
6936 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6937 }
6938 }
6939 for(auto q = 0; q < subscreens_map.size(); ++q)
6940 {
6941 size_t indx = movelist->move_refs.size();
6942 collect_subscreen_tiles(subscreens_map[q], *movelist.get());
6943 for(; indx < movelist->move_refs.size(); ++indx)
6944 {
6945 auto& ref = movelist->move_refs[indx];
6946 ref->name = fmt::format("Map Subscr {} - {}", q, ref->name);
6947 }
6948 }
6949 if(!every_proc && !movelist->check_prot())
6950 return false;
6951 }
6952 //Strings
6953 {
6954 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6955 dest_process, source_process, mode,
6956 move
6957 ? "The tiles used by the following strings will be partially cleared by the move."
6958 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6959 ));
6960 for(size_t q = 0; q < msg_count; ++q)
6961 {
6962 MsgStr& str = MsgStrings[q];
6963 std::string text = str.serialize();
6964 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6965 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6966 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(text,100)));
6967 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6968 fmt::format("{} (Port.): '{}'", q, util::snip(text,100)));
6969 }
6970 if(!every_proc && !movelist->check_prot())
6971 return false;
6972 }
6973
6974 if(source_process) //Apply the 'diff' value to all moved tiles
6975 storage.redo();
6976 if(every_proc)
6977 for(auto &list : vec)
6978 for(auto &ref : list->move_refs)
6979 ref->forEach(every_proc);
6980 return true;
6981 }
6982 bool handle_tile_move(TileMoveProcess dest_process)
6983 {
6984 return _handle_tile_move(dest_process, nullopt, 0);
6985 }
6986 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6987 {
6988 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6989 }
6990 void for_every_used_tile(std::function<void(int32_t)> proc)
6991 {
6992 reset_combo_animations();
6993 reset_combo_animations2();
6994 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6995 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6996 }
6997
6998 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6999 {
7000 bool move = source_process.has_value();
7001 ComboMoveUndo local_undo;
7002 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
7003 auto& vec = storage.vec;
7004 auto& combo_links = storage.combo_links;
7005 storage.diff = diff;
7006 storage.state = false;
7007 //Combo relative links
7008 {
7009 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7010 {
7011 newcombo& cmb = combobuf[q];
7012 for(size_t idx = 0; idx < cmb.triggers.size(); ++idx)
7013 {
7014 auto& trig = cmb.triggers[idx];
7015 if(trig.trigchange)
7016 combo_links.add_to(q, q+trig.trigchange);
7017 }
7018 bool next = cmb.flag == mfSECRETSNEXT;
7019 switch(cmb.type)
7020 {
7021 case cPOUND:
7022 case cLOCKBLOCK: case cLOCKBLOCK2:
7023 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7024 case cCHEST: case cCHEST2:
7025 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7026 case cBOSSCHEST: case cBOSSCHEST2:
7027 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7028 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7029 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7030 case cTALLGRASSNEXT: case cCRUMBLE:
7031 next = true;
7032 break;
7033 case cCSWITCH: case cCSWITCHBLOCK:
7034 combo_links.add_to(q, q+cmb.attributes[0]);
7035 break;
7036 case cLIGHTTARGET:
7037 if(cmb.usrflags & cflag1)
7038 combo_links.add_to(q, q-1);
7039 else next = true;
7040 break;
7041 case cSTEPSFX:
7042 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7043 next = true;
7044 break;
7045 }
7046 if(next)
7047 combo_links.add_to(q, q+1);
7048 }
7049 }
7050
7051 //This function is expensive! Any optimizations possible should be made. -Em
7052
7053 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7054 #define ADDC(ptr, str) \
7055 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7056 #define ADDC_10k(ptr, str) \
7057 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7058 //Combos
7059 {
7060 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7061 combo_links, dest_process, source_process,
7062 move
7063 ? "The combos used by the following combos will be partially cleared by the move."
7064 : "The combos used by the following combos will be partially or completely overwritten by this process."
7065 ));
7066 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7067 {
7068 newcombo& cmb = combobuf[q];
7069 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7070 : fmt::format(" ({})", cmb.label));
7071 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7072 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7073 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7074 for(auto& trig : cmb.triggers)
7075 ADDC(&trig.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7076
7077 //type-specific
7078 char const* type_name = ZI.getComboTypeName(cmb.type);
7079 switch(cmb.type)
7080 {
7081 case cLOCKEDCHEST: case cBOSSCHEST:
7082 if(cmb.usrflags & cflag13)
7083 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7084 [[fallthrough]];
7085 case cCHEST:
7086 if(cmb.usrflags & cflag13)
7087 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7088 break;
7089 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7090 if(cmb.usrflags & cflag13)
7091 {
7092 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7093 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7094 }
7095 break;
7096 case cSIGNPOST:
7097 if(cmb.usrflags & cflag13)
7098 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7099 break;
7100 case cBUTTONPROMPT:
7101 if(cmb.usrflags & cflag13)
7102 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7103 break;
7104 }
7105 }
7106
7107 if(!movelist->check_prot())
7108 return false;
7109 }
7110 //Door Combo Sets
7111 {
7112 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7113 combo_links, dest_process, source_process,
7114 move
7115 ? "The combos used by the following screens will be partially cleared by the move."
7116 : "The combos used by the following screens will be partially or completely overwritten by this process."
7117 ));
7118 static const char* door_names[9] = {
7119 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7120 };
7121 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7122 {
7123 auto& dcs = DoorComboSets[i];
7124 auto& name = DoorComboSetNames[i];
7125 for(int32_t j=0; j<9; j++)
7126 {
7127 if(j<4)
7128 {
7129 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7130
7131 if(j<3)
7132 {
7133 if(j<2)
7134 {
7135 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7136 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7137 }
7138 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7139 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7140 }
7141 }
7142
7143 for(int32_t k=0; k<6; k++)
7144 {
7145 if(k<4)
7146 {
7147 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7148 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7149 }
7150
7151 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7152 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7153 }
7154 }
7155 }
7156
7157 if(!movelist->check_prot())
7158 return false;
7159 }
7160 //Combo Pools
7161 {
7162 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7163 combo_links, dest_process, source_process,
7164 move
7165 ? "The combos used by the following combo pools will be partially cleared by the move."
7166 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7167 ));
7168 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7169 {
7170 combo_pool& pool = combo_pools[q];
7171 int idx = 0;
7172 for(cpool_entry& cp : pool.combos)
7173 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7174 }
7175
7176 if(!movelist->check_prot())
7177 return false;
7178 }
7179 //Auto Combos
7180 {
7181 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7182 combo_links, dest_process, source_process,
7183 move
7184 ? "The combos used by the following autocombos will be partially cleared by the move."
7185 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7186 ));
7187 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7188 {
7189 combo_auto& cauto = combo_autos[q];
7190 int idx = 0;
7191 for (autocombo_entry& ac : cauto.combos)
7192 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7193 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7194 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7195 }
7196
7197 if(!movelist->check_prot())
7198 return false;
7199 }
7200 //Combo Aliases
7201 {
7202 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7203 combo_links, dest_process, source_process,
7204 move
7205 ? "The combos used by the following aliases will be partially cleared by the move."
7206 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7207 ));
7208 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7209 {
7210 //dimensions are 1 less than you would expect -DD
7211 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7212
7213 for(int32_t j=0; j<count; j++)
7214 {
7215 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7216 }
7217 }
7218
7219 if(!movelist->check_prot())
7220 return false;
7221 }
7222 //Favorite Combos
7223 {
7224 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7225 combo_links, dest_process, source_process,
7226 move
7227 ? "The combos used by the following favorite combos will be partially cleared by the move."
7228 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7229 ));
7230 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7231 {
7232 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7233 continue;
7234 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7235 }
7236
7237 if(!movelist->check_prot())
7238 return false;
7239 }
7240 //Bottle Shops
7241 {
7242 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7243 combo_links, dest_process, source_process,
7244 move
7245 ? "The combos used by the following bottle shops will be partially cleared by the move."
7246 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7247 ));
7248 for(auto q = 0; q < 256; ++q)
7249 for(auto p = 0; p < 3; ++p)
7250 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7251
7252 if(!movelist->check_prot())
7253 return false;
7254 }
7255 //Screens //EXPENSIVE! DO THIS LAST!
7256 {
7257 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7258 combo_links, dest_process, source_process,
7259 move
7260 ? "The combos used by the following screens will be partially cleared by the move."
7261 : "The combos used by the following screens will be partially or completely overwritten by this process."
7262 ));
7263
7264 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7265 {
7266 for(int32_t j=0; j<MAPSCRS; j++)
7267 {
7268 mapscr& scr = TheMaps[i*MAPSCRS+j];
7269
7270 if(!(scr.valid&mVALID))
7271 continue;
7272
7273 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7274
7275 // Specifying the exact position is too expensive - too much string creation.
7276 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7277 for(int32_t k=0; k<176; k++)
7278 ADDC(&scr.data[k], data_str);
7279
7280 for(int32_t k=0; k<128; k++)
7281 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7282
7283 word maxffc = scr.numFFC();
7284 for(word k=0; k<maxffc; k++)
7285 {
7286 ffcdata& ffc = scr.ffcs[k];
7287 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7288 }
7289 }
7290 }
7291
7292 if(!movelist->check_prot())
7293 return false;
7294 }
7295 if(source_process) //Apply the 'diff' value to all moved combos
7296 storage.redo();
7297 return true;
7298 }
7299
7300 bool handle_combo_move(ComboMoveProcess dest_process)
7301 {
7302 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7303 }
7304 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7305 {
7306 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7307 }
7308 void register_used_tiles()
7309 {
7310 memset(used_tile_table, 0, sizeof(used_tile_table));
7311 for_every_used_tile([&](int tile)
7312 {
7313 used_tile_table[tile] = true;
7314 });
7315 }
7316
7317 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7318 {
7319 bool ctrl=(CHECK_CTRL_CMD);
7320 bool copied=false;
7321 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7322
7323 if(copied)
7324 {
7325 saved=false;
7326 }
7327
7328 return copied;
7329 }
7330
7331 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7332 {
7333 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7334 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7335
7336 // if tile>tile2 then swap them
7337 if(tile>tile2)
7338 {
7339 zc_swap(tile, tile2);
7340 }
7341
7342 // alt=copy from right
7343 // shift=copy from bottom
7344
7345 int32_t copies=copycnt;
7346 int32_t dest_first=tile;
7347 int32_t dest_last=tile2;
7348 int32_t src_first=copy;
7349 int32_t src_last=copy+copies-1;
7350
7351 int32_t dest_top=0;
7352 int32_t dest_bottom=0;
7353 int32_t src_top=0;
7354 int32_t src_bottom=0;
7355 int32_t src_left=0, src_right=0;
7356 int32_t src_width=0, src_height=0;
7357 int32_t dest_left=0, dest_right=0;
7358 int32_t dest_width=0, dest_height=0;
7359 int32_t rows=0, cols=0;
7360
7361 if(rect)
7362 {
7363 dest_top=TILEROW(dest_first);
7364 dest_bottom=TILEROW(dest_last);
7365 src_top=TILEROW(src_first);
7366 src_bottom=TILEROW(src_last);
7367
7368 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7369 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7370 src_first=(src_top * TILES_PER_ROW)+src_left;
7371 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7372
7373 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7374 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7375 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7376 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7377
7378 //if no dest range set, then set one
7379 if((dest_first==dest_last)&&(src_first!=src_last))
7380 {
7381 if(alt)
7382 {
7383 dest_left=dest_right-(src_right-src_left);
7384 }
7385 else
7386 {
7387 dest_right=dest_left+(src_right-src_left);
7388 }
7389
7390 if(shift)
7391 {
7392 dest_top=dest_bottom-(src_bottom-src_top);
7393 }
7394 else
7395 {
7396 dest_bottom=dest_top+(src_bottom-src_top);
7397 }
7398
7399 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7400 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7401 }
7402 else
7403 {
7404 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7405 {
7406 if(alt) //copy from right tile instead of left
7407 {
7408 src_left=src_right-(dest_right-dest_left);
7409 }
7410 else //copy from left tile
7411 {
7412 src_right=src_left+(dest_right-dest_left);
7413 }
7414 }
7415 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7416 {
7417 if(alt) //copy from right tile instead of left
7418 {
7419 dest_left=dest_right-(src_right-src_left);
7420 }
7421 else //copy from left tile
7422 {
7423 dest_right=dest_left+(src_right-src_left);
7424 }
7425 }
7426
7427 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7428 {
7429 if(shift) //copy from bottom tile instead of top
7430 {
7431 src_top=src_bottom-(dest_bottom-dest_top);
7432 }
7433 else //copy from top tile
7434 {
7435 src_bottom=src_top+(dest_bottom-dest_top);
7436 }
7437 }
7438 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7439 {
7440 if(shift) //copy from bottom tile instead of top
7441 {
7442 dest_top=dest_bottom-(src_bottom-src_top);
7443 }
7444 else //copy from top tile
7445 {
7446 dest_bottom=dest_top+(src_bottom-src_top);
7447 }
7448 }
7449
7450 src_first=(src_top * TILES_PER_ROW)+src_left;
7451 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7452 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7453 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7454 }
7455
7456 cols=src_right-src_left+1;
7457 rows=src_bottom-src_top+1;
7458
7459 dest_width=dest_right-dest_left+1;
7460 dest_height=dest_bottom-dest_top+1;
7461 src_width=src_right-src_left+1;
7462 src_height=src_bottom-src_top+1;
7463
7464 }
7465 else //!rect
7466 {
7467 //if no dest range set, then set one
7468 if((dest_first==dest_last)&&(src_first!=src_last))
7469 {
7470 if(alt)
7471 {
7472 dest_first=dest_last-(src_last-src_first);
7473 }
7474 else
7475 {
7476 dest_last=dest_first+(src_last-src_first);
7477 }
7478 }
7479 else
7480 {
7481 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7482 {
7483 if(alt) //copy from last tile instead of first
7484 {
7485 src_first=src_last-(dest_last-dest_first);
7486 }
7487 else //copy from first tile
7488 {
7489 src_last=src_first+(dest_last-dest_first);
7490 }
7491 }
7492 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7493 {
7494 if(alt) //copy from last tile instead of first
7495 {
7496 dest_first=dest_last-(src_last-src_first);
7497 }
7498 else //copy from first tile
7499 {
7500 dest_last=dest_first+(src_last-src_first);
7501 }
7502 }
7503 }
7504
7505 copies=dest_last-dest_first+1;
7506 }
7507
7508
7509
7510 char buf2[80], buf3[80], buf4[80];
7511 sprintf(buf2, " ");
7512 sprintf(buf3, " ");
7513 sprintf(buf4, " ");
7514
7515 // warn if range extends beyond last tile
7516 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7517
7518 if(dest_last>=NEWMAXTILES)
7519 {
7520 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7521 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7522 return false;
7523 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7524 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7525 // {
7526 // return false;
7527 // }
7528 }
7529
7530
7531 TileMoveUndo on_undo;
7532 // Overwrite warnings
7533 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7534 if(move)
7535 {
7536 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7537 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7538 return false;
7539 }
7540 else
7541 {
7542 if(!handle_tile_move(dest))
7543 return false;
7544 }
7545 // copy tiles and delete if needed (move)
7546
7547 {
7548 go_tiles();
7549
7550 int32_t diff=dest_first-src_first;
7551
7552 if(rect)
7553 {
7554 for(int32_t r=0; r<rows; ++r)
7555 {
7556 for(int32_t c=0; c<cols; ++c)
7557 {
7558 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7559 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7560
7561 if(dt>=NEWMAXTILES)
7562 continue;
7563
7564 overlay_tile(newtilebuf,dt,st,cs,backwards);
7565
7566 }
7567 }
7568 }
7569 else
7570 {
7571 for(int32_t c=0; c<copies; ++c)
7572 {
7573 int32_t dt=(dest_first+c);
7574 int32_t st=(src_first+c);
7575
7576 if(dt>=NEWMAXTILES)
7577 continue;
7578
7579 overlay_tile(newtilebuf,dt,st,cs,backwards);
7580
7581 if(move)
7582 {
7583 if(st<dest_first||st>(dest_first+c-1))
7584 reset_tile(newtilebuf, st, tf4Bit);
7585 }
7586 }
7587 }
7588 }
7589
7590 //now that tiles have moved, fix these buffers -DD
7591 register_blank_tiles();
7592 register_used_tiles();
7593
7594 if(move)
7595 last_tile_move_list = std::move(on_undo);
7596 return true;
7597 }
7598 //
7599 bool do_movetile_united(tile_move_data const& tmd)
7600 {
7601 char buf2[80], buf3[80], buf4[80];
7602 sprintf(buf2, " ");
7603 sprintf(buf3, " ");
7604 sprintf(buf4, " ");
7605
7606 // warn if range extends beyond last tile
7607 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7608
7609 if(tmd.dest_last>=NEWMAXTILES)
7610 {
7611 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7612 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7613 return false;
7614 }
7615
7616 TileMoveUndo on_undo;
7617 // Overwrite warnings
7618 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7619 if(tmd.move)
7620 {
7621 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7622 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7623 return false;
7624 }
7625 else
7626 {
7627 if(!handle_tile_move(dest))
7628 return false;
7629 }
7630
7631 // copy tiles and delete if needed (tmd.move)
7632 {
7633 go_tiles();
7634
7635 if(tmd.rect)
7636 {
7637 for(int32_t r=0; r<tmd.rows; ++r)
7638 {
7639 for(int32_t c=0; c<tmd.cols; ++c)
7640 {
7641 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7642 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7643
7644 if(dt>=NEWMAXTILES)
7645 continue;
7646
7647 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7648
7649 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7650 {
7651 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7652 }
7653
7654 if(tmd.move)
7655 {
7656 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7657 reset_tile(newtilebuf, st, tf4Bit);
7658 else
7659 {
7660 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7661 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7662 if(destLeft<=destRight)
7663 {
7664 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7665 reset_tile(newtilebuf, st, tf4Bit);
7666 }
7667 else // Wrapped around
7668 {
7669 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7670 reset_tile(newtilebuf, st, tf4Bit);
7671 }
7672 }
7673 }
7674 }
7675 }
7676 }
7677 else
7678 {
7679 for(int32_t c=0; c<tmd.copies; ++c)
7680 {
7681 int32_t dt=(tmd.dest_first+c);
7682 int32_t st=(tmd.src_first+c);
7683
7684 if(dt>=NEWMAXTILES)
7685 continue;
7686
7687 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7688
7689 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7690 {
7691 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7692 }
7693
7694 if(tmd.move)
7695 {
7696 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7697 reset_tile(newtilebuf, st, tf4Bit);
7698 }
7699 }
7700 }
7701 }
7702
7703 //now that tiles have moved, fix these buffers -DD
7704 register_blank_tiles();
7705 register_used_tiles();
7706
7707 if(tmd.move)
7708 last_tile_move_list = std::move(on_undo);
7709 return true;
7710 }
7711
7712 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7713 {
7714 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7715 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7716
7717 // if tile>tile2 then swap them
7718 if(tile>tile2)
7719 {
7720 zc_swap(tile, tile2);
7721 }
7722
7723 // alt=copy from right
7724 // shift=copy from bottom
7725 tile_move_data tmd;
7726
7727 tmd.copies=copycnt;
7728 tmd.dest_first=tile;
7729 tmd.dest_last=tile2;
7730 tmd.src_first=copy;
7731 tmd.src_last=copy+tmd.copies-1;
7732 tmd.rect = rect;
7733 tmd.move = move;
7734
7735 if(rect)
7736 {
7737 tmd.dest_top=TILEROW(tmd.dest_first);
7738 tmd.dest_bottom=TILEROW(tmd.dest_last);
7739 tmd.src_top=TILEROW(tmd.src_first);
7740 tmd.src_bottom=TILEROW(tmd.src_last);
7741
7742 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7743 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7744 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7745 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7746
7747 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7748 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7749 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7750 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7751
7752 //if no dest range set, then set one
7753 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7754 {
7755 if(alt)
7756 {
7757 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7758 }
7759 else
7760 {
7761 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7762 }
7763
7764 if(shift)
7765 {
7766 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7767 }
7768 else
7769 {
7770 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7771 }
7772
7773 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7774 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7775 }
7776 else
7777 {
7778 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7779 {
7780 if(alt) //copy from right tile instead of left
7781 {
7782 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7783 }
7784 else //copy from left tile
7785 {
7786 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7787 }
7788 }
7789 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7790 {
7791 if(alt) //copy from right tile instead of left
7792 {
7793 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7794 }
7795 else //copy from left tile
7796 {
7797 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7798 }
7799 }
7800
7801 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7802 {
7803 if(shift) //copy from bottom tile instead of top
7804 {
7805 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7806 }
7807 else //copy from top tile
7808 {
7809 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7810 }
7811 }
7812 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7813 {
7814 if(shift) //copy from bottom tile instead of top
7815 {
7816 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7817 }
7818 else //copy from top tile
7819 {
7820 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7821 }
7822 }
7823
7824 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7825 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7826 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7827 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7828 }
7829
7830 tmd.cols=tmd.src_right-tmd.src_left+1;
7831 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7832
7833 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7834 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7835 tmd.src_width=tmd.src_right-tmd.src_left+1;
7836 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7837
7838 }
7839 else //!rect
7840 {
7841 //if no dest range set, then set one
7842 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7843 {
7844 if(alt)
7845 {
7846 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7847 }
7848 else
7849 {
7850 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7851 }
7852 }
7853 else
7854 {
7855 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7856 {
7857 if(alt) //copy from last tile instead of first
7858 {
7859 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7860 }
7861 else //copy from first tile
7862 {
7863 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7864 }
7865 }
7866 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7867 {
7868 if(alt) //copy from last tile instead of first
7869 {
7870 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7871 }
7872 else //copy from first tile
7873 {
7874 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7875 }
7876 }
7877 }
7878
7879 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7880 }
7881
7882 return do_movetile_united(tmd);
7883 }
7884
7885 //
7886
7887 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7888 {
7889 assert(!move); //not implemented
7890
7891 // if tile>tile2 then swap them
7892 if(tile>tile2)
7893 {
7894 zc_swap(tile, tile2);
7895 }
7896
7897 tile_move_data tmd;
7898 tmd.copies=copycnt;
7899 tmd.dest_first=tile;
7900 tmd.dest_last=tile2;
7901 tmd.src_first=copy;
7902 tmd.src_last=copy+tmd.copies-1;
7903
7904
7905
7906 if(rect)
7907 {
7908 tmd.dest_top=TILEROW(tmd.dest_first);
7909 tmd.dest_bottom=TILEROW(tmd.dest_last);
7910 //tmd.src_top=TILEROW(tmd.src_first);
7911 //tmd.src_bottom=TILEROW(tmd.src_last);
7912
7913 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7914 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7915 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7916 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7917
7918 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7919 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7920 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7921 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7922
7923
7924
7925
7926 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7927 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7928
7929 tmd.cols=tmd.dest_width+1;
7930 tmd.rows=tmd.dest_height+1;
7931
7932 al_trace("tmd.rows: %d\n", tmd.rows);
7933 al_trace("tmd.cols: %d\n", tmd.cols);
7934
7935
7936 }
7937 else //!rect
7938 {
7939 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7940 }
7941
7942
7943
7944 char buf2[80], buf3[80], buf4[80];
7945 sprintf(buf2, " ");
7946 sprintf(buf3, " ");
7947 sprintf(buf4, " ");
7948
7949 // warn if range extends beyond last tile
7950 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7951
7952 if(tmd.dest_last>=NEWMAXTILES)
7953 {
7954 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7955 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7956 return false;
7957 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7958 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7959 // {
7960 // return false;
7961 // }
7962 }
7963
7964 TileMoveUndo on_undo;
7965 // Overwrite warnings
7966 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7967 if(tmd.move)
7968 {
7969 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7970 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7971 return false;
7972 }
7973 else
7974 {
7975 if(!handle_tile_move(dest))
7976 return false;
7977 }
7978
7979 // copy tiles and delete if needed (move)
7980
7981 {
7982 go_tiles();
7983
7984 int32_t diff=tmd.dest_first-tmd.src_first;
7985
7986 if(rect)
7987 {
7988 al_trace("floodfill, rect\n");
7989 al_trace("tmd.rows: %d\n", tmd.rows);
7990 al_trace("tmd.cols: %d\n", tmd.cols);
7991 for(int32_t r=0; r<tmd.rows; ++r)
7992 {
7993 for(int32_t c=0; c<tmd.cols; ++c)
7994 {
7995 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7996 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7997
7998 if(dt>=NEWMAXTILES)
7999 continue;
8000
8001 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8002
8003 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8004 {
8005 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8006 }
8007 }
8008 }
8009 }
8010 else
8011 {
8012 for(int32_t c=0; c<tmd.copies; ++c)
8013 {
8014 int32_t dt=(tmd.dest_first+c);
8015 int32_t st=(tmd.src_first+c);
8016
8017 if(dt>=NEWMAXTILES)
8018 continue;
8019
8020 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8021
8022 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8023 {
8024 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8025 }
8026
8027 }
8028 }
8029 }
8030
8031 //now that tiles have moved, fix these buffers -DD
8032 register_blank_tiles();
8033 register_used_tiles();
8034
8035 if(tmd.move)
8036 last_tile_move_list = std::move(on_undo);
8037 return true;
8038 }
8039 //
8040
8041 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8042 {
8043 al_trace("Floodfill Psste\n");
8044 bool ctrl=(CHECK_CTRL_CMD);
8045 bool copied=false;
8046 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8047
8048 if(copied)
8049 {
8050 if(!ctrl)
8051 {
8052 copy=-1;
8053 tile2=tile;
8054 }
8055
8056 saved=false;
8057 }
8058
8059 return copied;
8060 }
8061
8062 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8063 {
8064 bool ctrl=(CHECK_CTRL_CMD);
8065 bool copied=false;
8066 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8067
8068 if(copied)
8069 {
8070 if(!ctrl)
8071 {
8072 copy=-1;
8073 tile2=tile;
8074 }
8075
8076 saved=false;
8077 }
8078
8079 return copied;
8080 }
8081
8082 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8083 {
8084 // if tile>tile2 then swap them
8085 if(tile>tile2)
8086 {
8087 zc_swap(tile, tile2);
8088 }
8089 int32_t src_top = TILEROW(tile);
8090 int32_t src_bottom = TILEROW(tile2);
8091 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8092 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8093 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8094 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8095
8096 int32_t src_width = src_right-src_left+1,
8097 src_height = src_bottom-src_top+1;
8098 int32_t dest_width = src_width, dest_height = src_height;
8099 zfix dest_rot = 0_zf;
8100 if(rotate)
8101 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8102 else
8103 ScaleTileDialog(&dest_width, &dest_height).show();
8104 if (rotate)
8105 {
8106 if (dest_rot == 0) return false;
8107 }
8108 else
8109 {
8110 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8111 }
8112 dest_width = vbound(dest_width, 1, 20);
8113 dest_height = vbound(dest_height, 1, 20);
8114
8115 int32_t dest_top = src_top;
8116 int32_t dest_bottom = src_top+dest_height-1;
8117 int32_t dest_left = src_left;
8118 int32_t dest_right = src_left+dest_width-1;
8119 int32_t dest_first = src_first;
8120 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8121
8122
8123 if(dest_last>=NEWMAXTILES)
8124 {
8125 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8126 return false;
8127 }
8128
8129 // Overwrite warnings
8130 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8131 return false;
8132
8133 //Do the rotate
8134 {
8135 go_tiles();
8136
8137 int32_t diff=dest_first-src_first;
8138 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8139 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8140 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8141 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8142 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8143 if (rotate)
8144 {
8145 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8146 }
8147 else
8148 {
8149 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8150 0, 0, destbmp->w, destbmp->h);
8151 }
8152 int32_t mhei = zc_max(src_height,dest_height),
8153 mwid = zc_max(src_width, dest_width);
8154 for(int32_t r=0; r<mhei; ++r)
8155 {
8156 for(int32_t c=0; c<mwid; ++c)
8157 {
8158 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8159
8160 if(dt>=NEWMAXTILES)
8161 continue;
8162 if(r < dest_height && c < dest_width)
8163 {
8164 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8165 }
8166 else reset_tile(newtilebuf, dt, tf4Bit);
8167 }
8168 }
8169 }
8170
8171 register_blank_tiles();
8172 register_used_tiles();
8173 return true;
8174 }
8175
8176 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8177 {
8178 //these 2 shouldn't be needed, but just to be safe...
8179 reset_combo_animations();
8180 reset_combo_animations2();
8181
8182 if(tile2<tile)
8183 {
8184 zc_swap(tile,tile2);
8185 }
8186
8187 auto first = tile;
8188 auto last = masscopy ? tile2 : first + copycnt-1;
8189 if(!handle_combo_move({first,last}))
8190 return;
8191
8192 if(!masscopy)
8193 {
8194 if(tile==copy)
8195 {
8196 copy=-1;
8197 tile2=tile;
8198 return;
8199 }
8200
8201 // go_combos(); // commented because caller does it for us
8202 //if copying to an earlier combo, copy from left to right
8203 //otherwise, copy from right to left
8204 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8205 {
8206 if(tile+t < MAXCOMBOS)
8207 {
8208 combobuf[tile+t]=combobuf[copy+t];
8209 }
8210 }
8211
8212 copy=-1;
8213 tile2=tile;
8214 saved=false;
8215 }
8216 else
8217 {
8218 // go_combos();
8219 int32_t src=copy, dest=tile;
8220
8221 do
8222 {
8223 combobuf[dest]=combobuf[src];
8224 ++src;
8225 ++dest;
8226
8227 if((src-copy)==copycnt) src=copy;
8228 }
8229 while(dest<=tile2);
8230
8231 copy=-1;
8232 tile2=tile;
8233 saved=false;
8234 }
8235
8236 setup_combo_animations();
8237 setup_combo_animations2();
8238 }
8239
8240 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8241 {
8242 reset_combo_animations();
8243 reset_combo_animations2();
8244 go_combos();
8245
8246 auto diff = cmd.tile - cmd.copy1;
8247 if(is_undoing)
8248 on_undo.undo();
8249 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8250 return false;
8251
8252 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8253 {
8254 if(cmd.tile+t < MAXCOMBOS)
8255 {
8256 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8257 clear_combo(cmd.copy1+t);
8258 }
8259 }
8260
8261 setup_combo_animations();
8262 setup_combo_animations2();
8263 saved=false;
8264 return true;
8265 }
8266
8267 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8268 {
8269 if(tile2<tile)
8270 {
8271 zc_swap(tile,tile2);
8272 }
8273
8274 if(tile==copy)
8275 {
8276 copy=-1;
8277 tile2=tile;
8278 return;
8279 }
8280
8281 combo_move_data cmd;
8282 cmd.tile = tile;
8283 cmd.tile2 = tile2;
8284 cmd.copy1 = copy;
8285 cmd.copycnt = copycnt;
8286
8287 ComboMoveUndo on_undo;
8288 if(!do_movecombo(cmd, on_undo))
8289 return;
8290 last_combo_move_list = std::move(on_undo);
8291 copy=-1;
8292 tile2=tile;
8293 }
8294
8295 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8296 {
8297 if(firsttile > lasttile)
8298 zc_swap(firsttile,lasttile);
8299 int32_t coldiff = 0;
8300 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8301 {
8302 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8303 firsttile-=coldiff;
8304 lasttile+=coldiff;
8305 }
8306 for(int32_t t=firsttile; t<=lasttile; ++t)
8307 if(!rect_sel ||
8308 ((TILECOL(t)>=TILECOL(firsttile)) &&
8309 (TILECOL(t)<=TILECOL(lasttile))))
8310 reset_tile(newtilebuf, t, tf4Bit);
8311 saved=false;
8312 register_blank_tiles();
8313 }
8314
8315 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8316 {
8317 char buf[40];
8318
8319 if(tile==tile2)
8320 {
8321 sprintf(buf,"Delete tile %d?",tile);
8322 }
8323 else
8324 {
8325 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8326 }
8327
8328 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8329 {
8330 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8331
8332 go_tiles();
8333
8334 //if copying to an earlier tile, copy from left to right
8335 //otherwise, copy from right to left
8336 do_delete_tiles(firsttile, lasttile, rect_sel);
8337
8338 tile=tile2=zc_min(tile,tile2);
8339 saved=false;
8340 register_blank_tiles();
8341 }
8342 }
8343
8344 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8345 {
8346 byte buf[256];
8347 go_tiles();
8348
8349 unpack_tile(newtilebuf, dest, 0, false);
8350
8351 for(int32_t i=0; i<256; i++)
8352 buf[i] = unpackbuf[i];
8353
8354 unpack_tile(newtilebuf, src, 0, false);
8355
8356 if(newtilebuf[src].format>tf4Bit)
8357 {
8358 cs=0;
8359 }
8360
8361 cs &= 15;
8362 cs <<= CSET_SHFT;
8363
8364 for(int32_t i=0; i<256; i++)
8365 {
8366 if(backwards)
8367 {
8368 if(!buf[i])
8369 {
8370 buf[i] = unpackbuf[i]+cs;
8371 }
8372 }
8373 else
8374 {
8375 if(unpackbuf[i])
8376 {
8377 buf[i] = unpackbuf[i]+cs;
8378 }
8379 }
8380 }
8381
8382 pack_tile(newtilebuf, buf,dest);
8383 saved=false;
8384 }
8385
8386 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8387 {
8388 //byte buf[256];
8389 go_tiles();
8390
8391 if(!rect_sel)
8392 {
8393 for(int32_t d=dest1; d <= dest2; ++d)
8394 {
8395 /*unpack_tile(newtilebuf, d, 0, false);
8396
8397 for(int32_t i=0; i<256; i++)
8398 {
8399 if(!backwards)
8400 {
8401 if(!buf[i])
8402 {
8403 buf[i] = unpackbuf[i] + cs;
8404 }
8405 }
8406 else
8407 {
8408 if(unpackbuf[i])
8409 {
8410 buf[i] = unpackbuf[i] + cs;
8411 }
8412 }
8413 }
8414
8415 pack_tile(newtilebuf, buf,d);
8416 */
8417
8418 overlay_tile(newtilebuf,d,src,cs,backwards);
8419
8420 if(!blank_tile_table[src])
8421 {
8422 blank_tile_table[d]=false;
8423 }
8424 }
8425 }
8426 else
8427 {
8428 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8429 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8430 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8431 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8432 int32_t d=0;
8433
8434 for(int32_t j=cmin; j<=cmax; ++j)
8435 {
8436 for(int32_t k=rmin; k<=rmax; ++k)
8437 {
8438 d=j+TILES_PER_ROW*k;
8439 /*unpack_tile(newtilebuf, d, 0, false);
8440
8441 for(int32_t i=0; i<256; i++)
8442 {
8443 if(!backwards)
8444 {
8445 if(!buf[i])
8446 {
8447 buf[i] = unpackbuf[i] + cs;
8448 }
8449 }
8450 else
8451 {
8452 if(unpackbuf[i])
8453 {
8454 buf[i] = unpackbuf[i] + cs;
8455 }
8456 }
8457 }
8458
8459 pack_tile(newtilebuf, buf,d);
8460 */
8461
8462 overlay_tile(newtilebuf,d,src,cs,backwards);
8463
8464 if(!blank_tile_table[src])
8465 {
8466 blank_tile_table[d]=false;
8467 }
8468 }
8469 }
8470 }
8471
8472 return;
8473 }
8474
8475 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8476 {
8477 tile+=s;
8478 bound(tile,0,NEWMAXTILES-1);
8479
8480 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8481 tile2 = tile;
8482
8483 first = tile - (tile%TILES_PER_PAGE);
8484 }
8485
8486 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8487 {
8488 int32_t cst;
8489
8490 switch(bp2)
8491 {
8492 case tf4Bit:
8493 switch(newtilebuf[t].format)
8494 {
8495 case tf4Bit:
8496 //already in the right format
8497 break;
8498
8499 case tf8Bit:
8500 unpack_tile(newtilebuf, t, 0, true);
8501
8502 if(alt) //reduce
8503 {
8504 for(int32_t i=0; i<256; i++)
8505 {
8506 if(!shift||unpackbuf[i]!=0)
8507 {
8508 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8509 }
8510 }
8511 }
8512 else //truncate
8513 {
8514 for(int32_t i=0; i<256; i++)
8515 {
8516 unpackbuf[i]&=15;
8517 }
8518 }
8519
8520 reset_tile(newtilebuf, t, tf4Bit);
8521 pack_tile(newtilebuf, unpackbuf, t);
8522 break;
8523 }
8524
8525 break;
8526
8527 case tf8Bit:
8528 switch(newtilebuf[t].format)
8529 {
8530 case tf4Bit:
8531 unpack_tile(newtilebuf, t, 0, true);
8532 cst = cs&15;
8533 cst <<= CSET_SHFT;
8534
8535 for(int32_t i=0; i<256; i++)
8536 {
8537 if(!shift||unpackbuf[i]!=0)
8538 {
8539 unpackbuf[i]+=cst;
8540 }
8541 }
8542
8543 reset_tile(newtilebuf, t, tf8Bit);
8544 pack_tile(newtilebuf, unpackbuf, t);
8545 break;
8546
8547 case tf8Bit:
8548 //already in the right format
8549 break;
8550 }
8551
8552 break;
8553 }
8554 }
8555
8556 static DIALOG create_relational_tiles_dlg[] =
8557 {
8558 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8559 12 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8560 12 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8561 12 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8562 12 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8563 12 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8564 12 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8565 12 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8566 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8567 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8568 };
8569
8570 void draw_tile_list_window()
8571 {
8572 int32_t w = 640;
8573 int32_t h = 480;
8574
8575 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8576 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8577 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8578 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8579
8580 FONT *oldfont = font;
8581 font = get_zc_font(font_lfont);
8582 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8583 font=oldfont;
8584 return;
8585 }
8586
8587 void show_blank_tile(int32_t t)
8588 {
8589 char tbuf[80], tbuf2[80], tbuf3[80];
8590 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8591 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8592 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8593 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8594 }
8595
8596 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8597 {
8598 int num_bits;
8599 if (format == tf4Bit)
8600 num_bits = 4;
8601 else if (format == tf8Bit)
8602 num_bits = 8;
8603 else assert(false);
8604
8605 char buf[80];
8606 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8607
8608 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8609 {
8610 go_tiles();
8611 saved=false;
8612
8613 if(format == tf4Bit)
8614 {
8615 memset(cset_reduce_table, 0, 256);
8616 memset(col_diff,0,3*128);
8617 calc_cset_reduce_table(RAMpal, cs);
8618 }
8619
8620 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8621
8622 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8623 {
8624 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8625 firsttile-=coldiff;
8626 lasttile+=coldiff;
8627 }
8628
8629 for(int32_t t=firsttile; t<=lasttile; t++)
8630 if(!rect_sel ||
8631 ((TILECOL(t)>=TILECOL(firsttile)) &&
8632 (TILECOL(t)<=TILECOL(lasttile))))
8633 convert_tile(t, format, cs, shift, alt);
8634
8635 tile=tile2=zc_min(tile,tile2);
8636 }
8637 }
8638
8639
8640 int32_t readtilefile(PACKFILE *f)
8641 {
8642 dword section_version=0;
8643 int32_t zversion = 0;
8644 int32_t zbuild = 0;
8645
8646 if(!p_igetl(&zversion,f))
8647 {
8648 return 0;
8649 }
8650 if(!p_igetl(&zbuild,f))
8651 {
8652 return 0;
8653 }
8654 if(!p_igetw(&section_version,f))
8655 {
8656 return 0;
8657 }
8658 if(!read_deprecated_section_cversion(f))
8659 {
8660 return 0;
8661 }
8662 al_trace("readoneweapon section_version: %d\n", section_version);
8663
8664 if ( zversion > ZELDA_VERSION )
8665 {
8666 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8667 return 0;
8668 }
8669
8670 else if ( ( section_version > V_TILES ))
8671 {
8672 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8673 return 0;
8674
8675 }
8676 else
8677 {
8678 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8679 }
8680
8681 int32_t index = 0;
8682 int32_t count = 0;
8683
8684 //tile id
8685 if(!p_igetl(&index,f))
8686 {
8687 return 0;
8688 }
8689 al_trace("Reading tile: index(%d)\n", index);
8690
8691 //tile count
8692 if(!p_igetl(&count,f))
8693 {
8694 return 0;
8695 }
8696 al_trace("Reading tile: count(%d)\n", count);
8697
8698
8699
8700
8701 for ( int32_t tilect = 0; tilect < count; tilect++ )
8702 {
8703 byte *temp_tile = new byte[tilesize(tf32Bit)];
8704 byte format=tf4Bit;
8705 memset(temp_tile, 0, tilesize(tf32Bit));
8706 if(!p_getc(&format,f))
8707 {
8708 delete[] temp_tile;
8709 return 0;
8710 }
8711
8712
8713 if(!pfread(temp_tile,tilesize(format),f))
8714 {
8715 delete[] temp_tile;
8716 return 0;
8717 }
8718
8719 reset_tile(newtilebuf, index+(tilect), format);
8720 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8721 delete[] temp_tile;
8722 }
8723
8724
8725 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8726
8727 register_blank_tiles();
8728 register_used_tiles();
8729
8730 return 1;
8731
8732 }
8733
8734 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8735 {
8736 dword section_version=0;
8737 int32_t zversion = 0;
8738 int32_t zbuild = 0;
8739
8740 if(!p_igetl(&zversion,f))
8741 {
8742 return 0;
8743 }
8744 if(!p_igetl(&zbuild,f))
8745 {
8746 return 0;
8747 }
8748 if(!p_igetw(&section_version,f))
8749 {
8750 return 0;
8751 }
8752 if(!read_deprecated_section_cversion(f))
8753 {
8754 return 0;
8755 }
8756 al_trace("readoneweapon section_version: %d\n", section_version);
8757
8758 if ( zversion > ZELDA_VERSION )
8759 {
8760 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8761 return 0;
8762 }
8763
8764 else if ( ( section_version > V_TILES ))
8765 {
8766 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8767 return 0;
8768
8769 }
8770 else
8771 {
8772 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8773 }
8774
8775 int32_t index = 0;
8776 int32_t count = 0;
8777
8778 //tile id
8779 if(!p_igetl(&index,f))
8780 {
8781 return 0;
8782 }
8783 al_trace("Reading tile: index(%d)\n", index);
8784
8785 //tile count
8786 if(!p_igetl(&count,f))
8787 {
8788 return 0;
8789 }
8790 al_trace("Reading tile: count(%d)\n", count);
8791
8792
8793 for ( int32_t tilect = 0; tilect < count; tilect++ )
8794 {
8795 byte *temp_tile = new byte[tilesize(tf32Bit)];
8796 byte format=tf4Bit;
8797 memset(temp_tile, 0, tilesize(tf32Bit));
8798 if(!p_getc(&format,f))
8799 {
8800 delete[] temp_tile;
8801 return 0;
8802 }
8803
8804
8805 if(!pfread(temp_tile,tilesize(format),f))
8806 {
8807 delete[] temp_tile;
8808 return 0;
8809 }
8810
8811 reset_tile(newtilebuf, start+(tilect), format);
8812 if ( skip )
8813 {
8814 if ( (start+(tilect)) < skip )
8815 {
8816 delete[] temp_tile;
8817 continue;
8818 }
8819
8820 }
8821 if ( start+(tilect) < NEWMAXTILES )
8822 {
8823 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8824 }
8825 delete[] temp_tile;
8826
8827 }
8828
8829
8830 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8831
8832 register_blank_tiles();
8833 register_used_tiles();
8834
8835 return 1;
8836
8837 }
8838
8839
8840 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8841 {
8842 dword section_version=0;
8843 int32_t zversion = 0;
8844 int32_t zbuild = 0;
8845
8846 if(!p_igetl(&zversion,f))
8847 {
8848 return 0;
8849 }
8850 if(!p_igetl(&zbuild,f))
8851 {
8852 return 0;
8853 }
8854 if(!p_igetw(&section_version,f))
8855 {
8856 return 0;
8857 }
8858 if(!read_deprecated_section_cversion(f))
8859 {
8860 return 0;
8861 }
8862 al_trace("readoneweapon section_version: %d\n", section_version);
8863
8864 if ( zversion > ZELDA_VERSION )
8865 {
8866 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8867 return 0;
8868 }
8869
8870 else if ( ( section_version > V_TILES ))
8871 {
8872 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8873 return 0;
8874
8875 }
8876 else
8877 {
8878 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8879 }
8880
8881 int32_t index = 0;
8882 int32_t count = 0;
8883
8884 //tile id
8885 if(!p_igetl(&index,f))
8886 {
8887 return 0;
8888 }
8889 al_trace("Reading tile: index(%d)\n", index);
8890
8891 //tile count
8892 if(!p_igetl(&count,f))
8893 {
8894 return 0;
8895 }
8896 al_trace("Reading tile: count(%d)\n", count);
8897
8898
8899
8900
8901 for ( int32_t tilect = 0; tilect < count; tilect++ )
8902 {
8903 byte *temp_tile = new byte[tilesize(tf32Bit)];
8904 byte format=tf4Bit;
8905 memset(temp_tile, 0, tilesize(tf32Bit));
8906
8907 if(!p_getc(&format,f))
8908 {
8909 delete[] temp_tile;
8910 return 0;
8911 }
8912
8913
8914 if(!pfread(temp_tile,tilesize(format),f))
8915 {
8916 delete[] temp_tile;
8917 return 0;
8918 }
8919
8920 reset_tile(newtilebuf, start+(tilect), format);
8921 if ( start+(tilect) < NEWMAXTILES )
8922 {
8923 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8924 }
8925 delete[] temp_tile;
8926 }
8927
8928
8929 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8930
8931 register_blank_tiles();
8932 register_used_tiles();
8933
8934 return 1;
8935
8936 }
8937 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8938 {
8939 dword section_version=V_TILES;
8940 int32_t zversion = ZELDA_VERSION;
8941 int32_t zbuild = VERSION_BUILD;
8942
8943 if(!p_iputl(zversion,f))
8944 {
8945 return 0;
8946 }
8947 if(!p_iputl(zbuild,f))
8948 {
8949 return 0;
8950 }
8951 if(!p_iputw(section_version,f))
8952 {
8953 return 0;
8954 }
8955
8956 if(!write_deprecated_section_cversion(section_version,f))
8957 {
8958 return 0;
8959 }
8960
8961 //start tile id
8962 if(!p_iputl(index,f))
8963 {
8964 return 0;
8965 }
8966
8967 //count
8968 if(!p_iputl(count,f))
8969 {
8970 return 0;
8971 }
8972
8973 for ( int32_t tilect = 0; tilect < count; tilect++ )
8974 {
8975 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8976 {
8977 return 0;
8978 }
8979 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8980 {
8981 return 0;
8982 }
8983 }
8984
8985 return 1;
8986
8987 }
8988
8989 static int32_t _selected_tile=-1, _selected_tcset=-1;
8990 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8991 {
8992 popup_zqdialog_start();
8993 reset_combo_animations();
8994 reset_combo_animations2();
8995 bound(tile,0,NEWMAXTILES-1);
8996 ex=exnow;
8997 int32_t done=0;
8998 int32_t oflip=flip;
8999 int32_t otile=tile;
9000 int32_t ocs=cs;
9001 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
9002 int32_t copy=-1;
9003 int32_t tile2=tile,copycnt=0;
9004 reftile = 0;
9005 int32_t tile_clicked=-1;
9006 bool rect_sel=true;
9007 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
9008 position_mouse_z(0);
9009
9010 register_used_tiles();
9011 int32_t w = 640;
9012 int32_t h = 480;
9013 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9014 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9015 int32_t screen_xofs=window_xofs+6;
9016 int32_t screen_yofs=window_yofs+25;
9017 int32_t panel_yofs=3;
9018 int32_t mul = 2;
9019 FONT *tfont = get_zc_font(font_lfont_l);
9020
9021 draw_tile_list_window();
9022 int32_t f=0;
9023 draw_tiles(first,cs,f);
9024
9025 if(type==0)
9026 {
9027 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9028 }
9029 else
9030 {
9031 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9032 }
9033
9034 go_tiles();
9035
9036 while(gui_mouse_b())
9037 {
9038 /* do nothing */
9039 rest(1);
9040 }
9041
9042 bool bdown=false;
9043
9044 #define FOREACH_START(_t) \
9045 { \
9046 int32_t _first, _last; \
9047 if(is_rect) \
9048 { \
9049 _first=top*TILES_PER_ROW+left; \
9050 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9051 } \
9052 else \
9053 { \
9054 _first=zc_min(tile, tile2); \
9055 _last=zc_max(tile, tile2); \
9056 } \
9057 for(int32_t _t=_first; _t<=_last; _t++) \
9058 { \
9059 if(is_rect) \
9060 { \
9061 int32_t row=TILEROW(_t); \
9062 if(row<top || row>=top+rows) \
9063 continue; \
9064 int32_t col=TILECOL(_t); \
9065 if(col<left || col>=left+columns) \
9066 continue; \
9067 } \
9068
9069 #define FOREACH_END\
9070 } \
9071 }
9072
9073 bool did_snap = false;
9074 int otl = tile, otl2 = tile2;
9075 do
9076 {
9077 HANDLE_CLOSE_ZQDLG();
9078 if(exiting_program) break;
9079 rest(4);
9080 int32_t top=TILEROW(zc_min(tile, tile2));
9081 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9082 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9083 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9084 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9085 bool redraw=false;
9086
9087 if(mouse_z!=0)
9088 {
9089 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9090 position_mouse_z(0);
9091 redraw=true;
9092 }
9093
9094 if(keypressed())
9095 {
9096 switch(readkey()>>8)
9097 {
9098 case KEY_ENTER_PAD:
9099 case KEY_ENTER:
9100 done=2;
9101 break;
9102
9103 case KEY_ESC:
9104 done=1;
9105 break;
9106
9107 case KEY_F1:
9108 onHelp();
9109 break;
9110
9111 case KEY_EQUALS:
9112 case KEY_PLUS_PAD:
9113 {
9114 if(CHECK_CTRL_CMD ||
9115 key[KEY_ALT] || key[KEY_ALTGR])
9116 {
9117 FOREACH_START(t)
9118 if(key[KEY_ALT] || key[KEY_ALTGR])
9119 shift_tile_colors(t, 16, false);
9120 else
9121 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9122 FOREACH_END
9123
9124 register_blank_tiles();
9125 }
9126 else if(edit_cs)
9127 cs = (cs<13) ? cs+1:0;
9128
9129 redraw=true;
9130 break;
9131 }
9132
9133 case KEY_Z:
9134 case KEY_F12:
9135 {
9136 if(!did_snap)
9137 {
9138 //Export tile page as screenshot
9139 PALETTE temppal;
9140 get_palette(temppal);
9141 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9142 draw_tiles(tempbmp,first,cs,f,false,true);
9143 save_bitmap(getSnapName(), tempbmp, RAMpal);
9144 destroy_bitmap(tempbmp);
9145
9146 redraw = true;
9147 did_snap = true;
9148 }
9149 break;
9150 }
9151
9152 case KEY_S:
9153 {
9154 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9155 break;
9156 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9157 if(!f) break;
9158 al_trace("Saving tile: %d\n", tile);
9159 writetilefile(f,tile,1);
9160 pack_fclose(f);
9161 break;
9162 }
9163 case KEY_L:
9164 {
9165 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9166 break;
9167 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9168 if(!f) break;
9169 al_trace("Saving tile: %d\n", tile);
9170 if (!readtilefile(f))
9171 {
9172 al_trace("Could not read from .ztile packfile %s\n", temppath);
9173 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9174 }
9175 else
9176 {
9177 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9178 }
9179
9180 pack_fclose(f);
9181 //register_blank_tiles();
9182 //register_used_tiles();
9183 redraw=true;
9184 break;
9185 }
9186 case KEY_MINUS:
9187 case KEY_MINUS_PAD:
9188 {
9189 if(CHECK_CTRL_CMD ||
9190 key[KEY_ALT] || key[KEY_ALTGR])
9191 {
9192 FOREACH_START(t)
9193 if(key[KEY_ALT] || key[KEY_ALTGR])
9194 shift_tile_colors(t, -16, false);
9195 else
9196 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9197 FOREACH_END
9198
9199 register_blank_tiles();
9200 }
9201 else if(edit_cs)
9202 cs = (cs>0) ? cs-1:13;
9203
9204 redraw=true;
9205 break;
9206 }
9207
9208 case KEY_UP:
9209 {
9210 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9211 {
9212 case 3: //ALT and CTRL
9213 case 2: //ALT
9214 if(is_rect)
9215 {
9216 saved=false;
9217 go_slide_tiles(columns, rows, top, left);
9218 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9219 bool same = true;
9220
9221 for(int32_t d=0; d<columns; d++)
9222 {
9223 for(int32_t s=0; s<rows; s++)
9224 {
9225 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9226
9227 if(newtilebuf[t].format!=bitcheck) same = false;
9228 }
9229 }
9230
9231 if(!same) break;
9232
9233 // This used to do something. Too lazy to remove.
9234 // Can probably remove the above "same" check too.
9235 bitcheck = 2;
9236
9237 for(int32_t c=0; c<columns; c++)
9238 {
9239 for(int32_t r=0; r<rows; r++)
9240 {
9241 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9242 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9243 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9244
9245 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9246 {
9247 if(pixelrow==15*bitcheck)
9248 {
9249 int32_t srctile=temptile+TILES_PER_ROW;
9250 if(srctile>=NEWMAXTILES)
9251 srctile-=rows*TILES_PER_ROW;
9252 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9253 }
9254
9255 *dest_pixelrow=*src_pixelrow;
9256 dest_pixelrow++;
9257 src_pixelrow++;
9258 }
9259 }
9260
9261 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9262
9263 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9264 {
9265 if((CHECK_CTRL_CMD))
9266 {
9267 *dest_pixelrow=0;
9268 }
9269 else
9270 {
9271 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9272 *dest_pixelrow=*src_pixelrow;
9273 }
9274 }
9275 }
9276 }
9277
9278 register_blank_tiles();
9279 redraw=true;
9280 break;
9281
9282 case 1: //CTRL
9283 case 0: //None
9284 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9285 redraw=true;
9286
9287 default: //Others
9288 break;
9289 }
9290 }
9291 break;
9292
9293 case KEY_DOWN:
9294 {
9295 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9296 {
9297 case 3: //ALT and CTRL
9298 case 2: //ALT
9299 if(is_rect)
9300 {
9301 saved=false;
9302 go_slide_tiles(columns, rows, top, left);
9303 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9304 bool same = true;
9305
9306 for(int32_t c=0; c<columns; c++)
9307 {
9308 for(int32_t r=0; r<rows; r++)
9309 {
9310 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9311
9312 if(newtilebuf[t].format!=bitcheck) same = false;
9313 }
9314 }
9315
9316 if(!same) break;
9317
9318 // This used to do something. Too lazy to remove.
9319 // Can probably remove the above "same" check too.
9320 bitcheck = 2;
9321
9322 for(int32_t c=0; c<columns; c++)
9323 {
9324 for(int32_t r=rows-1; r>=0; r--)
9325 {
9326 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9327 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9328 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9329
9330 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9331 {
9332 if(pixelrow<bitcheck)
9333 {
9334 int32_t srctile=temptile-TILES_PER_ROW;
9335 if(srctile<0)
9336 srctile+=rows*TILES_PER_ROW;
9337 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9338 *dest_pixelrow=*tempsrc;
9339 //*dest_pixelrow=0;
9340 }
9341 else
9342 {
9343 *dest_pixelrow=*src_pixelrow;
9344 }
9345
9346 dest_pixelrow--;
9347 src_pixelrow--;
9348 }
9349 }
9350
9351 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9352 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9353
9354 for(int32_t b=0; b<bitcheck; b++)
9355 {
9356 if((CHECK_CTRL_CMD))
9357 {
9358 *dest_pixelrow=0;
9359 }
9360 else
9361 {
9362 *dest_pixelrow=*src_pixelrow;
9363 }
9364
9365 dest_pixelrow++;
9366 src_pixelrow++;
9367 }
9368 }
9369 }
9370
9371 register_blank_tiles();
9372 redraw=true;
9373 break;
9374
9375 case 1: //CTRL
9376 case 0: //None
9377 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9378 redraw=true;
9379
9380 default: //Others
9381 break;
9382 }
9383 }
9384 break;
9385
9386 case KEY_LEFT:
9387 {
9388 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9389 {
9390 case 3: //ALT and CTRL
9391 case 2: //ALT
9392 if(is_rect)
9393 {
9394 saved=false;
9395 go_slide_tiles(columns, rows, top, left);
9396 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9397 bool same = true;
9398
9399 for(int32_t c=0; c<columns; c++)
9400 {
9401 for(int32_t r=0; r<rows; r++)
9402 {
9403 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9404
9405 if(newtilebuf[t].format!=bitcheck) same = false;
9406 }
9407 }
9408
9409 if(!same) break;
9410
9411 // This used to do something. Too lazy to remove.
9412 // Can probably remove the above "same" check too.
9413 bitcheck = 2;
9414
9415 for(int32_t r=0; r<rows; r++)
9416 {
9417 for(int32_t c=0; c<columns; c++)
9418 {
9419 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9420 byte *dest_pixelrow=(newtilebuf[temptile].data);
9421
9422 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9423 {
9424 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9425 {
9426 *dest_pixelrow=*(dest_pixelrow+1);
9427 dest_pixelrow++;
9428 }
9429
9430 if(c==columns-1)
9431 {
9432 if(!(CHECK_CTRL_CMD))
9433 {
9434 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9435 *dest_pixelrow=*tempsrc;
9436 }
9437 }
9438 else
9439
9440 {
9441 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9442 *dest_pixelrow=*tempsrc;
9443 }
9444
9445 dest_pixelrow++;
9446 }
9447 }
9448 }
9449
9450 register_blank_tiles();
9451 redraw=true;
9452 }
9453
9454 break;
9455
9456 case 1: //CTRL
9457 case 0: //None
9458 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9459 redraw=true;
9460
9461 default: //Others
9462 break;
9463 }
9464 }
9465 break;
9466
9467 case KEY_RIGHT:
9468 {
9469 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9470 {
9471 case 3: //ALT and CTRL
9472 case 2: //ALT
9473 if(is_rect)
9474 {
9475 saved=false;
9476 go_slide_tiles(columns, rows, top, left);
9477 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9478 bool same = true;
9479
9480 for(int32_t c=0; c<columns; c++)
9481 {
9482 for(int32_t r=0; r<rows; r++)
9483 {
9484 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9485
9486 if(newtilebuf[t].format!=bitcheck) same = false;
9487 }
9488 }
9489
9490 if(!same) break;
9491
9492 // This used to do something. Too lazy to remove.
9493 // Can probably remove the above "same" check too.
9494 bitcheck = 2;
9495
9496 for(int32_t r=0; r<rows; r++)
9497 {
9498 for(int32_t c=columns-1; c>=0; c--)
9499 {
9500 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9501 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9502
9503 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9504 {
9505 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9506 {
9507 *dest_pixelrow=*(dest_pixelrow-1);
9508 dest_pixelrow--;
9509 }
9510
9511 if(c==0)
9512 {
9513 if(!(CHECK_CTRL_CMD))
9514 {
9515 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9516 *dest_pixelrow=*tempsrc;
9517 }
9518 }
9519 else
9520 {
9521 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9522 *dest_pixelrow=*tempsrc;
9523 }
9524
9525 dest_pixelrow--;
9526 }
9527 }
9528 }
9529
9530 register_blank_tiles();
9531 redraw=true;
9532 }
9533
9534 break;
9535
9536 case 1: //CTRL
9537 case 0: //None
9538 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9539 redraw=true;
9540
9541 default: //Others
9542 break;
9543 }
9544 }
9545 break;
9546
9547 case KEY_PGUP:
9548 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9549 redraw=true;
9550 break;
9551
9552 case KEY_PGDN:
9553 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9554 redraw=true;
9555 break;
9556
9557 case KEY_HOME:
9558 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9559 redraw=true;
9560 break;
9561
9562 case KEY_END:
9563 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9564 redraw=true;
9565 break;
9566
9567 case KEY_P:
9568 {
9569 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9570
9571 if(whatPage >= 0)
9572 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9573
9574 break;
9575 }
9576
9577 case KEY_O:
9578 if(type==0 && copy>=0)
9579 {
9580 go_tiles();
9581
9582 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9583 {
9584 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9585 saved=false;
9586 }
9587 else
9588 {
9589 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9590 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9591 }
9592
9593 saved=false;
9594 redraw=true;
9595 }
9596
9597 break;
9598
9599 case KEY_E:
9600 if(type==0)
9601 {
9602 edit_tile(tile,flip,cs);
9603 draw_tile_list_window();
9604 redraw=true;
9605 }
9606
9607 break;
9608
9609 case KEY_G:
9610 if(type==0)
9611 {
9612 grab_tile(tile,cs);
9613 draw_tile_list_window();
9614 redraw=true;
9615 }
9616
9617 break;
9618
9619 case KEY_C:
9620 copy=zc_min(tile,tile2);
9621 copycnt=abs(tile-tile2)+1;
9622 redraw=true;
9623 break;
9624
9625 case KEY_X:
9626 if(type==2)
9627 {
9628 ex=(ex+1)%3;
9629 }
9630
9631 break;
9632
9633 case KEY_R:
9634 if(type==2)
9635 break;
9636 if(type==1)
9637 {
9638 flip = rotate_value(flip);
9639 redraw=true;
9640 break;
9641 }
9642
9643 go_tiles();
9644
9645 if(CHECK_CTRL_CMD)
9646 {
9647 bool go=false;
9648 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9649 go=true;
9650 else if(massRecolorSetup(cs))
9651 go=true;
9652
9653 if(go)
9654 {
9655 FOREACH_START(t)
9656 massRecolorApply(t);
9657 FOREACH_END
9658
9659 register_blank_tiles();
9660 }
9661 }
9662 else
9663 {
9664 FOREACH_START(t)
9665 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9666 FOREACH_END
9667 }
9668
9669 redraw=true;
9670 saved=false;
9671 break;
9672
9673 case KEY_SPACE:
9674 rect_sel=!rect_sel;
9675 copy=-1;
9676 redraw=true;
9677 break;
9678
9679 case KEY_H:
9680 flip^=1;
9681 go_tiles();
9682
9683 if(type==0)
9684 {
9685 normalize(tile,tile2,rect_sel,flip);
9686 flip=0;
9687 }
9688
9689 redraw=true;
9690 break;
9691
9692
9693 case KEY_V:
9694 if(copy==-1)
9695 {
9696 if(type!=2)
9697 {
9698 flip^=2;
9699 go_tiles();
9700
9701 if(type==0)
9702 {
9703 normalize(tile,tile2,rect_sel,flip);
9704 flip=0;
9705 }
9706 }
9707 }
9708 else
9709 {
9710 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9711 go_tiles();
9712 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9713 }
9714
9715 redraw=true;
9716 break;
9717
9718 case KEY_F:
9719 if(copy==-1)
9720 {
9721 break;
9722 }
9723 else
9724 {
9725 go_tiles();
9726 {
9727 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9728 }
9729 }
9730
9731 redraw=true;
9732 break;
9733
9734 case KEY_DEL:
9735 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9736 {
9737 bool warn = (rect_sel
9738 && ((tile/20)!=(tile2/20))
9739 && !(tile%20==0&&tile2%20==19));
9740 int32_t z=zc_min(tile,tile2);
9741 int32_t count = abs(tile-tile2) + 1;
9742 tile=z;
9743 tile2=NEWMAXTILES;
9744 copy = tile + count;
9745 copycnt = NEWMAXTILES-copy;
9746 char buf[64];
9747
9748 if(count>1)
9749 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9750 else
9751 sprintf(buf,"Remove tile %d?",tile);
9752
9753 AlertDialog("Remove Tiles", std::string(buf)
9754 +"\nThis will offset the tiles that follow!"
9755 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9756 [&](bool ret,bool)
9757 {
9758 if(ret)
9759 {
9760 go_tiles();
9761 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9762 {
9763 redraw=true;
9764 saved=false;
9765 }
9766 }
9767 }).show();
9768 }
9769 delete_tiles(tile,tile2,rect_sel);
9770 redraw=true;
9771 break;
9772
9773 case KEY_U:
9774 {
9775 if(CHECK_CTRL_CMD)
9776 {
9777 //Only toggle the first 2 bits!
9778 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9779 }
9780 else
9781 {
9782 comeback_tiles();
9783 }
9784
9785 redraw=true;
9786 }
9787 break;
9788
9789 case KEY_8:
9790 case KEY_8_PAD:
9791 hide_8bit_marker();
9792 break;
9793
9794 case KEY_I: //insert tiles
9795 if(type==0)
9796 {
9797 bool warn = (rect_sel
9798 && ((tile/20)!=(tile2/20))
9799 && !(tile%20==0&&tile2%20==19));
9800 int32_t z=zc_min(tile,tile2);
9801 int32_t count = abs(tile-tile2) + 1;
9802 tile=z;
9803 tile2=NEWMAXTILES;
9804 copy = tile + count;
9805 copycnt = NEWMAXTILES-copy;
9806
9807 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9808 {
9809 char buf[64];
9810
9811 if(count>1)
9812 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9813 else
9814 sprintf(buf,"Remove tile %d?",tile);
9815
9816 AlertDialog("Remove Tiles", std::string(buf)
9817 +"\nThis will offset the tiles that follow!"
9818 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9819 [&](bool ret,bool)
9820 {
9821 if(ret)
9822 {
9823 go_tiles();
9824 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9825 {
9826 redraw=true;
9827 saved=false;
9828 }
9829 }
9830 }).show();
9831 }
9832 else
9833 {
9834 char buf[64];
9835
9836 if(count>1)
9837 sprintf(buf,"Insert %d blank tiles?",count);
9838 else
9839 sprintf(buf,"Insert a blank tile?");
9840
9841 AlertDialog("Insert Tiles", std::string(buf)
9842 +"\nThis will offset the tiles that follow!"
9843 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9844 [&](bool ret,bool)
9845 {
9846 if(ret)
9847 {
9848 go_tiles();
9849 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9850 {
9851 redraw=true;
9852 saved=false;
9853 }
9854 }
9855 }).show();
9856 }
9857
9858 copy=-1;
9859 tile2=tile=z;
9860 }
9861 break;
9862 case KEY_M:
9863 if(type==0)
9864 {
9865 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9866 {
9867 go_tiles();
9868 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9869 saved=false;
9870 }
9871 else if(copy==-1)
9872 {
9873 // I don't know what this was supposed to be doing before.
9874 // It didn't work in anything like a sensible way.
9875 if(rect_sel)
9876 {
9877 make_combos_rect(top, left, rows, columns, cs);
9878 }
9879 else
9880 {
9881 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9882 }
9883 }
9884
9885 redraw=true;
9886 }
9887 break;
9888
9889 case KEY_D:
9890 {
9891 int32_t frames=1;
9892 char buf[80];
9893 sprintf(buf, "%d", frames);
9894 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9895 create_relational_tiles_dlg[2].dp=buf;
9896
9897 large_dialog(create_relational_tiles_dlg);
9898
9899 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9900
9901 if(ret==5)
9902 {
9903 frames=zc_max(atoi(buf),1);
9904 bool same = true;
9905 int32_t bitcheck=newtilebuf[tile].format;
9906
9907 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9908 {
9909 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9910 }
9911
9912 if(!same)
9913 {
9914 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9915 break;
9916 }
9917
9918 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9919 {
9920 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9921 break;
9922 }
9923
9924 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9925 {
9926 reset_tile(newtilebuf, tile+i, bitcheck);
9927 }
9928
9929 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9930 {
9931 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9932 {
9933 for(int32_t j=0; j<frames; ++j)
9934 {
9935 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9936 }
9937 }
9938 }
9939 else
9940 {
9941 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9942 {
9943 for(int32_t j=0; j<frames; ++j)
9944 {
9945 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9946 }
9947 }
9948 }
9949 }
9950 register_blank_tiles();
9951 register_used_tiles();
9952 redraw=true;
9953 saved=false;
9954 break;
9955 }
9956
9957 case KEY_B:
9958 {
9959 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9960 bool control=(CHECK_CTRL_CMD);
9961 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9962 int format = control ? tf4Bit : tf8Bit;
9963
9964 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9965 register_blank_tiles();
9966 }
9967 break;
9968 }
9969
9970 clear_keybuf();
9971 }
9972
9973 if(!(key[KEY_Z] || key[KEY_F12]))
9974 did_snap = false;
9975
9976 if(gui_mouse_b()&1)
9977 {
9978 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9979 {
9980 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9981 {
9982 done=1;
9983 }
9984 }
9985
9986 int32_t x=gui_mouse_x()-screen_xofs;
9987 int32_t y=gui_mouse_y()-screen_yofs;
9988
9989 if(y>=0 && y<208*mul)
9990 {
9991 x=zc_min(zc_max(x,0),(320*mul)-1);
9992 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9993
9994 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9995 {
9996 tile2=t;
9997 }
9998 else
9999 {
10000 tile=tile2=t;
10001 }
10002
10003 if(tile_clicked!=t)
10004 {
10005 dclick_status=DCLICK_NOT;
10006 }
10007 else if(dclick_status == DCLICK_AGAIN)
10008 {
10009 while(gui_mouse_b())
10010 {
10011 /* do nothing */
10012 rest(1);
10013 }
10014
10015 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10016 {
10017 dclick_status=DCLICK_NOT;
10018 }
10019 else
10020 {
10021 if(type==0)
10022 {
10023 edit_tile(tile,flip,cs);
10024 draw_tile_list_window();
10025 redraw=true;
10026 }
10027 else
10028 {
10029 done=2;
10030 }
10031 }
10032 }
10033
10034 tile_clicked=t;
10035 }
10036 else if(x>300*mul && !bdown)
10037 {
10038 if(y<224*mul && first>0)
10039 {
10040 first-=TILES_PER_PAGE;
10041 redraw=true;
10042 }
10043
10044 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10045 {
10046 first+=TILES_PER_PAGE;
10047 redraw=true;
10048 }
10049
10050 bdown=true;
10051 }
10052
10053 if(type==1||type==2)
10054 {
10055 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10056 done=1;
10057
10058 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10059 done=2;
10060 }
10061 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10062 {
10063 rect_sel=!rect_sel;
10064 copy=-1;
10065 redraw=true;
10066 }
10067 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10068 {
10069 FONT *tf = font;
10070 font = tfont;
10071
10072 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10073 {
10074 font = tf;
10075 grab_tile(tile,cs);
10076 draw_tile_list_window();
10077 position_mouse_z(0);
10078 redraw=true;
10079 }
10080
10081 font = tf;
10082 }
10083 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10084 {
10085 FONT *tf = font;
10086 font = tfont;
10087
10088 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10089 {
10090 font = tf;
10091 edit_tile(tile,flip,cs);
10092 draw_tile_list_window();
10093 redraw=true;
10094 }
10095
10096 font = tf;
10097 }
10098 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10099 {
10100 FONT *tf = font;
10101 font = tfont;
10102
10103 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10104 {
10105 std::string initial_path = "tileset.png";
10106 if (strlen(datapath))
10107 initial_path = fmt::format("{}/{}", datapath, initial_path);
10108 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10109 {
10110 PALETTE temppal;
10111 get_palette(temppal);
10112 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10113 draw_tiles(tempbmp,first,cs,f,false,true);
10114 save_bitmap(temppath, tempbmp, RAMpal);
10115 destroy_bitmap(tempbmp);
10116 }
10117 }
10118
10119 font = tf;
10120 }
10121 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10122 {
10123 FONT *tf = font;
10124 font = tfont;
10125
10126 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10127 {
10128 if(massRecolorSetup(cs))
10129 {
10130 go_tiles();
10131
10132 FOREACH_START(t)
10133 massRecolorApply(t);
10134 FOREACH_END
10135
10136 register_blank_tiles();
10137 }
10138 }
10139
10140 font = tf;
10141 }
10142 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10143 {
10144 FONT *tf = font;
10145 font = tfont;
10146
10147 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10148 {
10149 done=1;
10150 }
10151
10152 font = tf;
10153 }
10154
10155 bdown=true;
10156 }
10157
10158 bool r_click = false;
10159
10160 if(gui_mouse_b()&2 && !bdown && type==0)
10161 {
10162 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10163 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10164
10165 if(y>=0 && y<208*mul)
10166 {
10167 x=zc_min(zc_max(x,0),(320*mul)-1);
10168 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10169
10170 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10171 tile=tile2=t;
10172 }
10173
10174 bdown = r_click = true;
10175 f=8;
10176 }
10177
10178 if(gui_mouse_b()==0)
10179 bdown=false;
10180
10181 position_mouse_z(0);
10182
10183 REDRAW:
10184
10185 if((f%8)==0 || InvalidBG == 1)
10186 redraw=true;
10187 if(otl != tile || otl2 != tile2)
10188 {
10189 otl = tile;
10190 otl2 = tile2;
10191 redraw = true;
10192 }
10193
10194 if(redraw)
10195 {
10196 draw_tiles(first,cs,f);
10197 }
10198 if(f&8)
10199 {
10200 if(rect_sel)
10201 {
10202 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10203 zc_min(TILECOL(tile),TILECOL(tile2));
10204 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10205 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10206 {
10207 if(i>=first && i<first+TILES_PER_PAGE &&
10208 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10209 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10210 {
10211 int32_t x=TILECOL(i)<<(5);
10212 int32_t y=TILEROW(i-first)<<(5);
10213 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10214 }
10215 }
10216 }
10217 else
10218 {
10219 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10220 {
10221 if(i>=first && i<first+TILES_PER_PAGE)
10222 {
10223 int32_t x=TILECOL(i)<<(5);
10224 int32_t y=TILEROW(i-first)<<(5);
10225 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10226 }
10227 }
10228 }
10229 }
10230
10231 if(type==0)
10232 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10233 else
10234 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10235
10236 if(type==2)
10237 {
10238 char cbuf[16];
10239 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10240 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10241 }
10242
10243 ++f;
10244
10245 if(r_click)
10246 {
10247 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10248 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10249 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10250 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10251
10252 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10253 if (newtilebuf[tile].format == tf8Bit)
10254 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10255 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10256 select_tile_color_depth_cb = [&](int format){
10257 if (newtilebuf[tile].format == format)
10258 return;
10259
10260 bool skip_prompt = true;
10261 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10262 };
10263
10264 NewMenu rcmenu
10265 {
10266 { "Copy", [&]()
10267 {
10268 copy = zc_min(tile,tile2);
10269 copycnt = abs(tile-tile2)+1;
10270 } },
10271 { "Paste", [&]()
10272 {
10273 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10274 if(saved) saved = !b;
10275 }, nullopt, copy < 0 ? MFL_DIS : 0 },
10276 { "Move", [&]()
10277 {
10278 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10279 if(saved) saved = !b;
10280 }, nullopt, copy < 0 ? MFL_DIS : 0 },
10281 { "Clear", [&]()
10282 {
10283 delete_tiles(tile, tile2, rect_sel);
10284 } },
10285 { "Set as Reference", [&]()
10286 {
10287 reftile = tile;
10288 } },
10289 {},
10290 { "Edit", [&]()
10291 {
10292 edit_tile(tile, flip, cs);
10293 draw_tile_list_window();
10294 } },
10295 { "Grab", [&]()
10296 {
10297 grab_tile(tile, cs);
10298 draw_tile_list_window();
10299 position_mouse_z(0);
10300 } },
10301 { "Scale", [&]()
10302 {
10303 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10304 if(saved) saved = !b;
10305 }, nullopt, type != 0 ? MFL_DIS : 0 },
10306 { "Angular Rotation", [&]()
10307 {
10308 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10309 if(saved) saved = !b;
10310 }, nullopt, type != 0 ? MFL_DIS : 0 },
10311 { "Color Depth", &select_tile_color_depth_menu },
10312 {},
10313 { "Blank?", [&]()
10314 {
10315 show_blank_tile(tile);
10316 } },
10317 {},
10318 { "View ", &select_tile_view_menu },
10319 { "Overlay", [&]()
10320 {
10321 overlay_tile(newtilebuf, tile, copy, cs, 0);
10322 } },
10323 { "H-Flip", [&]()
10324 {
10325 flip ^= 1;
10326 go_tiles();
10327
10328 if(type == 0)
10329 {
10330 normalize(tile, tile2, rect_sel, flip);
10331 flip = 0;
10332 }
10333 } },
10334 { "V-Flip", [&]()
10335 {
10336 flip ^= 2;
10337 go_tiles();
10338
10339 if(type == 0)
10340 {
10341 normalize(tile, tile2, rect_sel, flip);
10342 flip = 0;
10343 }
10344 } },
10345 { "Create Combos", [&]()
10346 {
10347 if(rect_sel)
10348 make_combos_rect(top, left, rows, columns, cs);
10349 else
10350 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10351 }, nullopt, type != 0 ? MFL_DIS : 0 },
10352 { "Insert", [&]()
10353 {
10354 bool warn = (rect_sel
10355 && ((tile/20)!=(tile2/20))
10356 && !(tile%20==0&&tile2%20==19));
10357 int32_t z = zc_min(tile, tile2);
10358 int32_t count = abs(tile-tile2) + 1;
10359 tile = z;
10360 tile2 = NEWMAXTILES;
10361 copy = tile + count;
10362 copycnt = NEWMAXTILES-copy;
10363
10364 string msg;
10365
10366 if(count>1)
10367 msg = fmt::format("Insert {} blank tiles?",count);
10368 else
10369 msg = "Insert a blank tile?";
10370
10371 AlertDialog("Insert Tiles", msg
10372 +"\nThis will offset the tiles that follow!"
10373 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10374 [&](bool ret,bool)
10375 {
10376 if(ret)
10377 {
10378 go_tiles();
10379 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10380 saved = false;
10381 }
10382 }).show();
10383
10384 copy=-1;
10385 tile2=tile=z;
10386 }, nullopt, type != 0 ? MFL_DIS : 0 },
10387 { "Remove", [&]()
10388 {
10389 bool warn = (rect_sel
10390 && ((tile/20)!=(tile2/20))
10391 && !(tile%20==0&&tile2%20==19));
10392 int32_t z = zc_min(tile, tile2);
10393 int32_t count = abs(tile-tile2) + 1;
10394 tile = z;
10395 tile2 = NEWMAXTILES;
10396 copy = tile + count;
10397 copycnt = NEWMAXTILES-copy;
10398
10399 string msg;
10400
10401 if(count>1)
10402 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10403 else
10404 msg = fmt::format("Remove tile {}?", tile);
10405
10406 AlertDialog("Remove Tiles", msg
10407 +"\nThis will offset the tiles that follow!"
10408 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10409 [&](bool ret,bool)
10410 {
10411 if(ret)
10412 {
10413 go_tiles();
10414 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10415 saved = false;
10416 }
10417 }).show();
10418
10419 copy=-1;
10420 tile2=tile=z;
10421 }, nullopt, type != 0 ? MFL_DIS : 0 },
10422 };
10423 rcmenu.pop(window_mouse_x(),window_mouse_y());
10424 redraw = true;
10425 r_click = false;
10426 goto REDRAW;
10427 }
10428 update_hw_screen();
10429 }
10430 while(!done);
10431
10432 while(gui_mouse_b())
10433 {
10434 /* do nothing */
10435 rest(1);
10436 }
10437
10438 register_blank_tiles();
10439 register_used_tiles();
10440 setup_combo_animations();
10441 setup_combo_animations2();
10442 int32_t ret = done-1;
10443 if(ret)
10444 {
10445 _selected_tile = tile;
10446 _selected_tcset = cs;
10447 }
10448
10449 popup_zqdialog_end();
10450 return ret;
10451 }
10452 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10453 {
10454 if(_selected_tile > -1)
10455 {
10456 tile = _selected_tile;
10457 cs = _selected_tcset;
10458 }
10459 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10460 if(_selected_tile < 0)
10461 {
10462 _selected_tile = tile;
10463 _selected_tcset = cs;
10464 }
10465 return ret;
10466 }
10467
10468 int32_t onTiles()
10469 {
10470 return onGotoTiles(-1);
10471 }
10472
10473 int32_t onGotoTiles(int32_t startfrom)
10474 {
10475 static int32_t t = 0;
10476 if (startfrom > -1)
10477 t = startfrom;
10478 int32_t f = 0;
10479 int32_t c = CSet;
10480 reset_pal_cycling();
10481 rebuild_trans_table();
10482 select_tile(t, f, 0, c, true);
10483 refresh(rALL);
10484 return D_O_K;
10485 }
10486
10487 int32_t combopage_animate = 1;
10488 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10489 {
10490 if(unsigned(c)<MAXCOMBOS)
10491 {
10492 newcombo& cmb = combobuf[c];
10493 int t = cmb.tile;
10494 if(!animate)
10495 cmb.tile = cmb.o_tile;
10496 put_combo(dest,x,y,c,cs,0,0);
10497 cmb.tile = t;
10498 }
10499 else
10500 {
10501 rectfill(dest,x,y,x+32-1,y+32-1,0);
10502 }
10503 }
10504
10505 void draw_combos(int32_t page,int32_t cs,bool cols)
10506 {
10507 clear_bitmap(screen2);
10508 BITMAP *buf = create_bitmap_ex(8,16,16);
10509
10510 int32_t w = 32;
10511 int32_t h = 32;
10512 int32_t mul = 2;
10513
10514 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10515 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10516 int32_t screen_xofs=window_xofs+6;
10517 int32_t screen_yofs=window_yofs+25;
10518
10519 if(cols==false)
10520 {
10521 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10522 {
10523 int32_t x = (i%COMBOS_PER_ROW)*w;
10524 int32_t y = (i/COMBOS_PER_ROW)*h;
10525
10526 combotile_override_x = x+screen_xofs+(w-16)/2;
10527 combotile_override_y = y+screen_yofs+(h-16)/2;
10528 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10529 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10530 }
10531 }
10532 else
10533 {
10534 int32_t c = 0;
10535
10536 for(int32_t i=0; i<256; i++)
10537 {
10538 int32_t x = (i%COMBOS_PER_ROW)*w;
10539 int32_t y = (i/COMBOS_PER_ROW)*h;
10540
10541 combotile_override_x = x+screen_xofs+(w-16)/2;
10542 combotile_override_y = y+screen_yofs+(h-16)/2;
10543 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10544 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10545 ++c;
10546
10547 if((i&3)==3)
10548 c+=48;
10549
10550 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10551 c-=256;
10552 }
10553 }
10554 combotile_override_x = combotile_override_y = -1;
10555
10556 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10557 {
10558 vline(screen2,x,0,(208*mul)-1,vc(15));
10559 }
10560
10561 destroy_bitmap(buf);
10562 }
10563
10564 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10565 {
10566 int32_t yofs=3;
10567 static BITMAP *buf = create_bitmap_ex(8,16,16);
10568 int32_t mul = 2;
10569 FONT *tfont = get_zc_font(font_lfont_l);
10570
10571 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10572 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10573 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10574
10575 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10576
10577 if(copy>=0)
10578 {
10579 put_combo(buf,0,0,copy,cs,0,0);
10580 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10581
10582 if(copycnt>1)
10583 {
10584 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10585 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10586 }
10587 else
10588 {
10589 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10590 }
10591 }
10592 else
10593 {
10594 if (InvalidBG == 2)
10595 {
10596 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10597 }
10598 else if(InvalidBG == 1)
10599 {
10600 for(int32_t dy=0; dy<16*mul; dy++)
10601 {
10602 for(int32_t dx=0; dx<16*mul; dx++)
10603 {
10604 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10605 }
10606 }
10607 }
10608 else
10609 {
10610 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10611 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10612 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10613 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10614 }
10615 }
10616
10617 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10618 put_combo(buf,0,0,tile,cs,0,0);
10619 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10620
10621 if(tile>tile2)
10622 {
10623 zc_swap(tile,tile2);
10624 }
10625
10626 char cbuf[8];
10627 cbuf[0]=0;
10628
10629 if(tile2!=tile)
10630 {
10631 sprintf(cbuf,"-%d",tile2);
10632 }
10633
10634 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10635 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10636
10637 if(tile2==tile)
10638 {
10639 int32_t nextcombo=combobuf[tile].nextcombo;
10640 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10641 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10642
10643 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10644 {
10645 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10646 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10647 }
10648 else
10649 {
10650 if (InvalidBG == 2)
10651 {
10652 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10653 }
10654 else if(InvalidBG == 1)
10655 {
10656 for(int32_t dy=0; dy<16*mul; dy++)
10657 {
10658 for(int32_t dx=0; dx<16*mul; dx++)
10659 {
10660 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10661 }
10662 }
10663 }
10664 else
10665 {
10666 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10667 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10668 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10669 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10670 }
10671 }
10672
10673 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10674 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10675 }
10676
10677
10678 FONT *tf = font;
10679 font = tfont;
10680
10681 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10682 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10683
10684 if(buttons&2)
10685 {
10686 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10687 }
10688
10689 if(buttons&4)
10690 {
10691 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10692 }
10693
10694 font = tf;
10695
10696 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10697 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10698 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10699 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10700
10701 int32_t w = 640;
10702 int32_t h = 480;
10703 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10704 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10705 int32_t screen_xofs=window_xofs+6;
10706 int32_t screen_yofs=window_yofs+25;
10707
10708 custom_vsync();
10709 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10710 }
10711
10712 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10713 {
10714 int32_t page = tile&0xFF00;
10715 tile &= 0xFF;
10716
10717 if(!cols)
10718 tile += s;
10719 else
10720 {
10721 if(s==-COMBOS_PER_ROW)
10722 tile-=4;
10723
10724 if(s==COMBOS_PER_ROW)
10725 tile+=4;
10726
10727 if(s==-1)
10728 tile-=1;
10729
10730 if(s==1)
10731 tile+=1;
10732 }
10733
10734 /*
10735 if(s==1)
10736 {
10737 if((tile&3)==3)
10738 tile+=48;
10739 else
10740 ++tile;
10741 }
10742 if(s==-1)
10743 {
10744 if((tile&3)==0)
10745 tile-=48;
10746 else
10747 --tile;
10748 }
10749 }
10750 */
10751 bound(tile,0,255);
10752 tile += page;
10753
10754 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10755 tile2 = tile;
10756 }
10757
10758 void draw_combo_list_window()
10759 {
10760 int32_t window_xofs=0;
10761 int32_t window_yofs=0;
10762 int32_t w = 640;
10763 int32_t h = 480;
10764
10765 window_xofs=(zq_screen_w-w-12)>>1;
10766 window_yofs=(zq_screen_h-h-25-6)>>1;
10767 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10768 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10769 FONT *oldfont = font;
10770 font = get_zc_font(font_lfont);
10771 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10772 font=oldfont;
10773 }
10774
10775
10776 static int32_t _selected_combo=-1, _selected_cset=-1;
10777 bool select_combo_2(int32_t &cmb,int32_t &cs)
10778 {
10779 popup_zqdialog_start();
10780 reset_combo_animations();
10781 reset_combo_animations2();
10782 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10783 // static int32_t cmb=0;
10784 int32_t page=cmb>>8;
10785 int32_t tile2=cmb;
10786 int32_t done=0;
10787 int32_t tile_clicked=-1;
10788 int32_t t2;
10789 int32_t copy=-1;
10790 int32_t copycnt=0;
10791
10792 position_mouse_z(0);
10793
10794 int32_t w = 640;
10795 int32_t h = 480;
10796 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10797 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10798 int32_t screen_xofs=window_xofs+6;
10799 int32_t screen_yofs=window_yofs+25;
10800 int32_t panel_yofs=3;
10801 int32_t mul = 2;
10802 FONT *tfont = get_zc_font(font_lfont_l);
10803
10804 draw_combo_list_window();
10805 draw_combos(page,cs,true);
10806 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10807
10808 while(gui_mouse_b())
10809 {
10810 /* do nothing */
10811 rest(1);
10812 }
10813
10814 bool bdown=false;
10815 int32_t f=0;
10816 int otl = cmb, otl2 = tile2;
10817
10818 do
10819 {
10820 HANDLE_CLOSE_ZQDLG();
10821 if(exiting_program) break;
10822 rest(4);
10823 bool redraw=false;
10824
10825 if(mouse_z<0)
10826 {
10827 if(page<COMBO_PAGES-1)
10828 {
10829 ++page;
10830 cmb=tile2=(page<<8)+(cmb&0xFF);
10831 }
10832
10833 position_mouse_z(0);
10834 redraw=true;
10835 }
10836 else if(mouse_z>0)
10837 {
10838 if(page>0)
10839 {
10840 --page;
10841 cmb=tile2=(page<<8)+(cmb&0xFF);
10842 }
10843
10844 position_mouse_z(0);
10845 redraw=true;
10846 }
10847
10848 if(keypressed())
10849 {
10850 switch(readkey()>>8)
10851 {
10852 case KEY_DEL:
10853 cmb=0;
10854 done=2;
10855 break;
10856
10857 case KEY_ENTER_PAD:
10858 case KEY_ENTER:
10859 done=2;
10860 break;
10861
10862 case KEY_ESC:
10863 done=1;
10864 break;
10865
10866 case KEY_F1:
10867 onHelp();
10868 break;
10869
10870 case KEY_EQUALS:
10871 case KEY_PLUS_PAD:
10872 cs = (cs<13) ? cs+1:0;
10873 redraw=true;
10874 break;
10875
10876 case KEY_MINUS:
10877 case KEY_MINUS_PAD:
10878 cs = (cs>0) ? cs-1:13;
10879 redraw=true;
10880 break;
10881
10882 case KEY_UP:
10883 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10884 redraw=true;
10885 break;
10886
10887 case KEY_DOWN:
10888 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10889 redraw=true;
10890 break;
10891
10892 case KEY_LEFT:
10893 sel_combo(cmb,tile2,-1,true);
10894 redraw=true;
10895 break;
10896
10897 case KEY_RIGHT:
10898 sel_combo(cmb,tile2,1,true);
10899 redraw=true;
10900 break;
10901
10902 case KEY_PGUP:
10903 if(page>0)
10904 {
10905 --page;
10906 cmb=tile2=(page<<8)+(cmb&0xFF);
10907 }
10908
10909 redraw=true;
10910 break;
10911
10912 case KEY_PGDN:
10913 if(page<COMBO_PAGES-1)
10914 {
10915 ++page;
10916 cmb=tile2=(page<<8)+(cmb&0xFF);
10917 }
10918
10919 redraw=true;
10920 break;
10921
10922 case KEY_P:
10923 {
10924 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10925
10926 if(!cancelgetnum)
10927 page=(zc_min(choosepage,COMBO_PAGES-1));
10928
10929 cmb=tile2=(page<<8)+(cmb&0xFF);
10930 redraw=true;
10931 break;
10932 }
10933 }
10934
10935 clear_keybuf();
10936 }
10937
10938 if(gui_mouse_b()&1)
10939 {
10940 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10941 {
10942 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10943 {
10944 done=1;
10945 }
10946 }
10947
10948 int32_t x=gui_mouse_x()-screen_xofs;
10949 int32_t y=gui_mouse_y()-screen_yofs;
10950
10951 if(y>=0 && y<208*mul)
10952 {
10953 x=zc_min(zc_max(x,0),(320*mul)-1);
10954 int32_t t;
10955
10956 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10957
10958 bound(t,0,255);
10959 t+=page<<8;
10960 cmb=tile2=t;
10961
10962 if(tile_clicked!=t)
10963 {
10964 dclick_status=DCLICK_NOT;
10965 }
10966 else if(dclick_status == DCLICK_AGAIN)
10967 {
10968 while(gui_mouse_b())
10969 {
10970 /* do nothing */
10971 }
10972
10973 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10974
10975 if(t2!=t)
10976 {
10977 dclick_status=DCLICK_NOT;
10978 }
10979 else
10980 {
10981 done=2;
10982 }
10983 }
10984
10985 tile_clicked=t;
10986 }
10987 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10988 {
10989 if(y<(224*mul)+panel_yofs && page>0)
10990 {
10991 --page;
10992 redraw=true;
10993 }
10994
10995 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10996 {
10997 ++page;
10998 redraw=true;
10999 }
11000
11001 bdown=true;
11002 }
11003
11004 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11005 {
11006 FONT *tf = font;
11007 font = tfont;
11008
11009 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11010 {
11011 done=2;
11012 }
11013
11014 font = tf;
11015 }
11016 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11017 {
11018 FONT *tf = font;
11019 font = tfont;
11020
11021 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11022 combopage_animate = combopage_animate ? 0 : 1;
11023 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11024 redraw = true;
11025
11026 font = tf;
11027 }
11028
11029 bdown=true;
11030 }
11031
11032 bool r_click = false;
11033
11034 if(gui_mouse_b()&2 && !bdown)
11035 {
11036 int32_t x=gui_mouse_x()+screen_xofs;
11037 int32_t y=gui_mouse_y()+screen_yofs;
11038
11039 if(y>=0 && y<208*mul)
11040 {
11041 x=zc_min(zc_max(x,0),(320*mul)-1);
11042 int32_t t;
11043
11044 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11045
11046 bound(t,0,255);
11047 t+=page<<8;
11048
11049 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11050 cmb=tile2=t;
11051 }
11052
11053 bdown = r_click = true;
11054 f=8;
11055 }
11056
11057 if(gui_mouse_b()==0)
11058 bdown=false;
11059
11060 if((f%8) || InvalidBG == 1)
11061 redraw = true;
11062 if(otl != cmb || otl2 != tile2)
11063 {
11064 otl = cmb;
11065 otl2 = tile2;
11066 redraw = true;
11067 }
11068
11069 if(redraw || combopage_animate)
11070 draw_combos(page,cs,true);
11071
11072 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11073
11074 if(f&8)
11075 {
11076 int32_t x,y;
11077
11078 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11079 {
11080 if((i>>8)==page)
11081 {
11082 int32_t t=i&255;
11083
11084 x=((t&3) + ((t/52)<<2)) << 5;
11085 y=((t%52)>>2) << 5;
11086
11087 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11088 }
11089 }
11090 }
11091
11092 ++f;
11093
11094 }
11095 while(!done);
11096
11097 while(gui_mouse_b())
11098 {
11099 /* do nothing */
11100 rest(1);
11101 }
11102
11103 setup_combo_animations();
11104 setup_combo_animations2();
11105
11106 bool ret = done==2;
11107 if(ret)
11108 {
11109 _selected_combo = cmb;
11110 _selected_cset = cs;
11111 }
11112
11113 popup_zqdialog_end();
11114 return ret;
11115 }
11116
11117 bool select_combo_3(int32_t &cmb,int32_t &cs)
11118 {
11119 if(_selected_combo < 0)
11120 {
11121 _selected_combo = Combo;
11122 _selected_cset = CSet;
11123 }
11124 cmb = _selected_combo;
11125 cs = _selected_cset;
11126 return select_combo_2(cmb,cs);
11127 }
11128
11129 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11130 {
11131 static bitstring pasteflags;
11132 static const vector<CheckListInfo> advp_names =
11133 {
11134 { "Tile" },
11135 { "CSet2" },
11136 { "Solidity" },
11137 { "Animation" },
11138 { "Type" },
11139 { "Inherent Flag" },
11140 { "Attributes", "Including Attribytes and Attrishorts" },
11141 { "Flags", "The 16 Flags on the 'Flags' tab" },
11142 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11143 { "Label" },
11144 { "Script" },
11145 { "Effect" },
11146 { "Triggers Tab" },
11147 { "Lifting Tab" },
11148 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11149 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11150 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11151 { "Gen: Z Height", "The combo's 'Z Height'/'Z Step Height' settings, and related flags" },
11152 { "Misc Weapon Data", "The combo's 'Misc Weapon Data' settings" },
11153 // should be CMB_ADVP_SZ long
11154 };
11155
11156 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11157 return false;
11158
11159 //Paste to each combo in the range
11160 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11161 combobuf[i].advpaste(combobuf[copy], pasteflags);
11162
11163 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11164 {
11165 setup_combo_animations();
11166 setup_combo_animations2();
11167 }
11168
11169 return true;
11170 }
11171
11172 int32_t combo_screen(int32_t pg, int32_t tl)
11173 {
11174 popup_zqdialog_start();
11175 reset_combo_animations();
11176 reset_combo_animations2();
11177 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11178 static int32_t tile=0;
11179 static int32_t page=0;
11180
11181 if(pg>-1)
11182 page = pg;
11183
11184 if(tl>-1)
11185 tile = tl;
11186
11187 int32_t tile2=tile;
11188 int32_t done=0;
11189 int32_t cs = CSet;
11190 int32_t copy=-1;
11191 int32_t copycnt=0;
11192
11193 int32_t tile_clicked=-1;
11194 int32_t t2;
11195
11196 bool masscopy;
11197
11198 int32_t w = 640;
11199 int32_t h = 480;
11200 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11201 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11202 int32_t screen_xofs=window_xofs+6;
11203 int32_t screen_yofs=window_yofs+25;
11204 int32_t panel_yofs=3;
11205 int32_t mul = 2;
11206 FONT *tfont = get_zc_font(font_lfont_l);
11207
11208 draw_combo_list_window();
11209 draw_combos(page,cs,true);
11210 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11211 go_combos();
11212 position_mouse_z(0);
11213
11214 while(gui_mouse_b())
11215 {
11216 /* do nothing */
11217 rest(1);
11218 }
11219
11220 bool bdown=false;
11221 int32_t f=0;
11222 int otl = tile, otl2 = tile2;
11223
11224 do
11225 {
11226 HANDLE_CLOSE_ZQDLG();
11227 if(exiting_program) break;
11228 rest(4);
11229 bool redraw=false;
11230
11231 if(mouse_z<0)
11232 {
11233 if(page<COMBO_PAGES-1)
11234 {
11235 ++page;
11236 tile=tile2=(page<<8)+(tile&0xFF);
11237 }
11238
11239 position_mouse_z(0);
11240 redraw=true;
11241 }
11242 else if(mouse_z>0)
11243 {
11244 if(page>0)
11245 {
11246 --page;
11247 tile=tile2=(page<<8)+(tile&0xFF);
11248 }
11249
11250 position_mouse_z(0);
11251 redraw=true;
11252 }
11253
11254 if(keypressed())
11255 {
11256 switch(readkey()>>8)
11257 {
11258 case KEY_ENTER_PAD:
11259 case KEY_ENTER:
11260 done=2;
11261 break;
11262
11263 case KEY_ESC:
11264 done=1;
11265 break;
11266
11267 case KEY_F1:
11268 onHelp();
11269 break;
11270
11271 case KEY_EQUALS:
11272 case KEY_PLUS_PAD:
11273 if(CHECK_CTRL_CMD)
11274 {
11275 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11276 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11277 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11278
11279 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11280 {
11281 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11282 0, NEWMAXTILES-1));
11283 }
11284
11285 setup_combo_animations();
11286 redraw=true;
11287 }
11288 else
11289 {
11290 cs = (cs<13) ? cs+1:0;
11291 redraw=true;
11292 }
11293
11294 break;
11295
11296 case KEY_MINUS:
11297 case KEY_MINUS_PAD:
11298 if(CHECK_CTRL_CMD)
11299 {
11300 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11301 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11302 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11303
11304 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11305 {
11306 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11307 0, NEWMAXTILES-1));
11308 }
11309
11310 setup_combo_animations();
11311 redraw=true;
11312 }
11313 else
11314 {
11315 cs = (cs>0) ? cs-1:13;
11316 redraw=true;
11317 }
11318
11319 break;
11320
11321 case KEY_UP:
11322 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11323 redraw=true;
11324 break;
11325
11326 case KEY_DOWN:
11327 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11328 redraw=true;
11329 break;
11330
11331 case KEY_LEFT:
11332 sel_combo(tile,tile2,-1,true);
11333 redraw=true;
11334 break;
11335
11336 case KEY_RIGHT:
11337 sel_combo(tile,tile2,1,true);
11338 redraw=true;
11339 break;
11340
11341 case KEY_PGUP:
11342 if(page>0)
11343 {
11344 --page;
11345 tile=tile2=(page<<8)+(tile&0xFF);
11346 }
11347
11348 redraw=true;
11349 break;
11350
11351 case KEY_PGDN:
11352 if(page<COMBO_PAGES-1)
11353 {
11354 ++page;
11355 tile=tile2=(page<<8)+(tile&0xFF);
11356 }
11357
11358 redraw=true;
11359 break;
11360
11361 case KEY_A:
11362 {
11363 tile=(page<<8);
11364 tile2=(page<<8)+(0xFF);
11365 }
11366
11367 redraw=true;
11368 break;
11369
11370 case KEY_P:
11371 {
11372 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11373
11374 if(!cancelgetnum)
11375 page=(zc_min(choosepage,COMBO_PAGES-1));
11376
11377 tile=tile2=(page<<8)+(tile&0xFF);
11378 redraw=true;
11379 }
11380 break;
11381
11382 case KEY_U:
11383 comeback_combos();
11384 redraw=true;
11385 break;
11386
11387 case KEY_E:
11388 go_combos();
11389 edit_combo(tile,false,cs);
11390 redraw=true;
11391 setup_combo_animations();
11392 setup_combo_animations2();
11393 break;
11394
11395 case KEY_C:
11396 go_combos();
11397 copy=zc_min(tile,tile2);
11398 copycnt=abs(tile-tile2)+1;
11399 redraw=true;
11400 break;
11401
11402 case KEY_H:
11403 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11404 {
11405 combobuf[i].flip^=1;
11406 byte w2=combobuf[i].walk;
11407 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11408 w2=combobuf[i].csets;
11409 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11410 }
11411
11412 redraw=true;
11413 saved=false;
11414 break;
11415
11416 case KEY_M:
11417 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11418 {
11419 move_combos(tile,tile2,copy,copycnt);
11420 saved=false;
11421 }
11422
11423 redraw=true;
11424 break;
11425
11426 case KEY_S:
11427 tile=tile2=zc_min(tile,tile2);
11428
11429 if(copy>=0 && tile!=copy)
11430 {
11431 go_combos();
11432
11433 for(int32_t i=0; i<copycnt; i++)
11434 {
11435 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11436 }
11437
11438 saved=false;
11439 setup_combo_animations();
11440 setup_combo_animations2();
11441 }
11442
11443 redraw=true;
11444 copy=-1;
11445 break;
11446
11447 case KEY_V:
11448 if((CHECK_CTRL_CMD) && copy != -1)
11449 {
11450 if(advpaste(tile, tile2, copy))
11451 {
11452 saved=false;
11453 redraw=true;
11454 copy=-1;
11455 }
11456
11457 break;
11458 }
11459
11460 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11461
11462 if(copy==-1)
11463 {
11464 go_combos();
11465
11466 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11467 {
11468 combobuf[i].flip^=2;
11469 byte w2=combobuf[i].walk;
11470 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11471 w2=combobuf[i].csets;
11472 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11473 }
11474
11475 saved=false;
11476 }
11477 else
11478 {
11479 go_combos();
11480 copy_combos(tile,tile2,copy,copycnt,masscopy);
11481 setup_combo_animations();
11482 setup_combo_animations2();
11483 saved=false;
11484 }
11485
11486 redraw=true;
11487 break;
11488 case KEY_R:
11489 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11490 {
11491 combobuf[i].flip = rotate_value(combobuf[i].flip);
11492 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11493 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11494 }
11495
11496 redraw=true;
11497 saved=false;
11498 break;
11499
11500 case KEY_I:
11501 {
11502 // rev.1509; Can now insert/remove all selected combos
11503 int32_t z=tile;
11504 int32_t numSelected = abs(tile-tile2) + 1;
11505 tile=zc_min(tile,tile2);
11506 tile2=MAXCOMBOS;
11507 copy = tile + numSelected; // copy=tile+1;
11508 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11509
11510 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11511 {
11512 char buf[64];
11513
11514 if(numSelected>1)
11515 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11516 else
11517 sprintf(buf,"Remove combo %d?",tile);
11518
11519 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11520 {
11521 move_combos(tile,tile2,copy, copycnt);
11522 //don't allow the user to undo; quest combo references are incorrect -DD
11523 go_combos();
11524 redraw=true;
11525 saved=false;
11526 }
11527 }
11528 else
11529 {
11530 char buf[64];
11531
11532 if(numSelected>1)
11533 sprintf(buf,"Insert %d blank combos?",numSelected);
11534 else
11535 sprintf(buf,"Insert a blank combo?");
11536
11537 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11538 {
11539 move_combos(copy,tile2,tile, copycnt);
11540 go_combos();
11541 redraw=true;
11542 saved=false;
11543 }
11544 }
11545
11546 copy=-1;
11547 tile2=tile=z;
11548 }
11549 break;
11550
11551 case KEY_DEL:
11552 {
11553 char buf[40];
11554
11555 if(tile==tile2)
11556 {
11557 sprintf(buf,"Delete combo %d?",tile);
11558 }
11559 else
11560 {
11561 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11562 }
11563
11564 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11565 {
11566 go_combos();
11567
11568 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11569 {
11570 clear_combo(i);
11571 }
11572
11573 tile=tile2=zc_min(tile,tile2);
11574 redraw=true;
11575 saved=false;
11576 setup_combo_animations();
11577 setup_combo_animations2();
11578 }
11579 }
11580 break;
11581 }
11582
11583 clear_keybuf();
11584 }
11585
11586 if(gui_mouse_b()&1)
11587 {
11588 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11589 {
11590 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11591 {
11592 done=1;
11593 }
11594 }
11595
11596 int32_t x=gui_mouse_x()-screen_xofs;
11597 int32_t y=gui_mouse_y()-screen_yofs;
11598
11599 if(y>=0 && y<(208*mul))
11600 {
11601 x=zc_min(zc_max(x,0),(320*mul)-1);
11602 int32_t t;
11603
11604 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11605
11606 bound(t,0,255);
11607 t+=page<<8;
11608
11609 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11610 {
11611 tile2=t;
11612 }
11613 else
11614 {
11615 tile=tile2=t;
11616 }
11617
11618 if(tile_clicked!=t)
11619 {
11620 dclick_status=DCLICK_NOT;
11621 }
11622 else if(dclick_status == DCLICK_AGAIN)
11623 {
11624 while(gui_mouse_b())
11625 {
11626 /* do nothing */
11627 rest(1);
11628 }
11629
11630 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11631
11632 bound(t2,0,255);
11633 t2+=page<<8;
11634
11635 if(t2!=t)
11636 {
11637 dclick_status=DCLICK_NOT;
11638 }
11639 else
11640 {
11641 go_combos();
11642 edit_combo(tile,false,cs);
11643 redraw=true;
11644 setup_combo_animations();
11645 setup_combo_animations2();
11646 }
11647 }
11648
11649 tile_clicked=t;
11650 }
11651 else if(x>(300*mul) && !bdown)
11652 {
11653 if(y<(224*mul)+panel_yofs && page>0)
11654 {
11655 --page;
11656 redraw=true;
11657 }
11658
11659 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11660 {
11661 ++page;
11662 redraw=true;
11663 }
11664
11665 bdown=true;
11666 }
11667
11668 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11669 {
11670 FONT *tf = font;
11671 font = tfont;
11672
11673 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11674 {
11675 font = tf;
11676 edit_combo(tile,false,cs);
11677 redraw=true;
11678 }
11679
11680 font = tf;
11681 }
11682 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11683 {
11684 FONT *tf = font;
11685 font = tfont;
11686
11687 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11688 {
11689 done=1;
11690 }
11691
11692 font = tf;
11693 }
11694 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11695 {
11696 FONT *tf = font;
11697 font = tfont;
11698
11699 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11700 combopage_animate = combopage_animate ? 0 : 1;
11701 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11702 redraw = true;
11703
11704 font = tf;
11705 }
11706
11707 bdown=true;
11708 }
11709
11710 bool r_click = false;
11711
11712 if(gui_mouse_b()&2 && !bdown)
11713 {
11714 int32_t x=gui_mouse_x()-screen_xofs;
11715 int32_t y=gui_mouse_y()-screen_yofs;
11716
11717 if(y>=0 && y<(208*mul))
11718 {
11719 x=zc_min(zc_max(x,0),(320*mul)-1);
11720 int32_t t;
11721
11722 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11723
11724 bound(t,0,255);
11725 t+=page<<8;
11726
11727 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11728 {
11729 tile=tile2=t;
11730 }
11731 }
11732
11733 bdown = r_click = true;
11734 f=8;
11735 }
11736
11737 REDRAW:
11738
11739 if(gui_mouse_b()==0)
11740 bdown=false;
11741
11742 if((f%8) || InvalidBG == 1)
11743 redraw = true;
11744 if(otl != tile || otl2 != tile2)
11745 {
11746 otl = tile;
11747 otl2 = tile2;
11748 redraw = true;
11749 }
11750
11751 if(redraw || combopage_animate)
11752 draw_combos(page,cs,true);
11753
11754 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11755
11756 if(f&8)
11757 {
11758 int32_t x,y;
11759
11760 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11761 {
11762 if((i>>8)==page)
11763 {
11764 int32_t t=i&255;
11765
11766 x=((t&3) + ((t/52)<<2)) << 5;
11767 y=((t%52)>>2) << 5;
11768
11769 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11770 }
11771 }
11772 }
11773
11774 ++f;
11775
11776 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11777 if(r_click)
11778 {
11779 NewMenu rcmenu
11780 {
11781 { "Copy", [&]()
11782 {
11783 go_combos();
11784 copy=zc_min(tile,tile2);
11785 copycnt=abs(tile-tile2)+1;
11786 } },
11787 { "Paste", [&]()
11788 {
11789 if((CHECK_CTRL_CMD))
11790 {
11791 if(advpaste(tile, tile2, copy))
11792 {
11793 saved=false;
11794 redraw=true;
11795 copy=-1;
11796 }
11797 return;
11798 }
11799
11800 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11801
11802 go_combos();
11803 copy_combos(tile,tile2,copy,copycnt,masscopy);
11804 setup_combo_animations();
11805 setup_combo_animations2();
11806 saved=false;
11807 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11808 { "Adv. Paste", [&]()
11809 {
11810 if(advpaste(tile, tile2, copy))
11811 {
11812 saved=false;
11813 redraw=true;
11814 copy=-1;
11815 }
11816 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11817 { "Move", [&]()
11818 {
11819 if(copy!=zc_min(tile,tile2))
11820 {
11821 move_combos(tile,tile2,copy,copycnt);
11822 saved=false;
11823 setup_combo_animations();
11824 setup_combo_animations2();
11825 }
11826 redraw=true;
11827 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11828 { "Swap", [&]()
11829 {
11830 tile=tile2=zc_min(tile,tile2);
11831
11832 if(tile!=copy)
11833 {
11834 go_combos();
11835
11836 for(int32_t i=0; i<copycnt; i++)
11837 {
11838 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11839 }
11840
11841 saved=false;
11842 setup_combo_animations();
11843 setup_combo_animations2();
11844 }
11845 copy=-1;
11846 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11847 { "Delete", [&]()
11848 {
11849 string msg;
11850
11851 if(tile==tile2)
11852 msg = fmt::format("Delete combo {}?",tile);
11853 else
11854 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11855 bool didconfirm = false;
11856 AlertDialog("Confirm Delete",msg,
11857 [&](bool ret,bool)
11858 {
11859 if(ret)
11860 didconfirm = true;
11861 }).show();
11862 if(didconfirm)
11863 {
11864 go_combos();
11865
11866 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11867 clear_combo(i);
11868
11869 tile=tile2=zc_min(tile,tile2);
11870 saved=false;
11871 }
11872 } },
11873 {},
11874 { "Edit", [&]()
11875 {
11876 go_combos();
11877 edit_combo(tile,false,cs);
11878 } },
11879 { "Insert", [&]()
11880 {
11881 int z = tile;
11882 int count = abs(tile-tile2)+1;
11883 tile = zc_min(tile,tile2);
11884 tile2 = MAXCOMBOS;
11885 copy = tile+count;
11886 copycnt = MAXCOMBOS-tile-count;
11887
11888 string msg;
11889
11890 if(count>1)
11891 msg = fmt::format("Insert combos {} - {}?"
11892 " This will offset all of the combos that follow!",tile, copy-1);
11893 else
11894 msg = fmt::format("Insert combo {}?"
11895 " This will offset all of the combos that follow!",tile);
11896
11897 bool didconfirm = false;
11898 AlertDialog("Confirm Insert",msg,
11899 [&](bool ret,bool)
11900 {
11901 if(ret)
11902 didconfirm = true;
11903 }).show();
11904 if(didconfirm)
11905 move_combos(copy, tile2, tile, copycnt);
11906 else return;
11907
11908 copy = -1;
11909 tile2 = tile = z;
11910
11911 //don't allow the user to undo; quest combo references are incorrect -DD
11912 go_combos();
11913 saved = false;
11914 } },
11915 { "Remove", [&]()
11916 {
11917 int z = tile;
11918 int count = abs(tile-tile2)+1;
11919 tile = zc_min(tile,tile2);
11920 tile2 = MAXCOMBOS;
11921 copy = tile+count;
11922 copycnt = MAXCOMBOS-tile-count;
11923
11924 string msg;
11925
11926 if(count>1)
11927 msg = fmt::format("Remove combos {} - {}?"
11928 " This will offset all of the combos that follow!",tile, copy-1);
11929 else
11930 msg = fmt::format("Remove combo {}?"
11931 " This will offset all of the combos that follow!",tile);
11932
11933 bool didconfirm = false;
11934 AlertDialog("Confirm Remove",msg,
11935 [&](bool ret,bool)
11936 {
11937 if(ret)
11938 didconfirm = true;
11939 }).show();
11940 if(didconfirm)
11941 move_combos(tile, tile2, copy, copycnt);
11942 else return;
11943
11944 copy = -1;
11945 tile2 = tile = z;
11946
11947 //don't allow the user to undo; quest combo references are incorrect -DD
11948 go_combos();
11949 saved = false;
11950 } },
11951 {},
11952 { "Locations", [&]()
11953 {
11954 int32_t z = Combo;
11955 Combo = tile;
11956 onComboLocationReport();
11957 Combo = z;
11958 } },
11959 };
11960 rcmenu.pop(window_mouse_x(),window_mouse_y());
11961 redraw = true;
11962 r_click = false;
11963 goto REDRAW;
11964 }
11965
11966 }
11967 while(!done);
11968
11969 while(gui_mouse_b())
11970 rest(1);
11971 setup_combo_animations();
11972 setup_combo_animations2();
11973 _selected_combo = tile;
11974 _selected_cset = cs;
11975 popup_zqdialog_end();
11976 return done-1;
11977 }
11978
11979 int32_t onCombos()
11980 {
11981 combo_screen(-1,-1);
11982 refresh(rALL);
11983 return D_O_K;
11984 }
11985
11986 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11987 {
11988 //these are here to bypass compiler warnings about unused arguments
11989 d=d;
11990 c=c;
11991
11992 if(msg==MSG_CLICK)
11993 {
11994 int32_t t=curr_combo.o_tile;
11995 int32_t f=curr_combo.flip;
11996
11997 if(select_tile(t,f,1,CSet,true,0,true))
11998 {
11999 curr_combo.tile=t;
12000 curr_combo.o_tile=t;
12001 curr_combo.flip=f;
12002 return D_REDRAW;
12003 }
12004 }
12005
12006 return D_O_K;
12007 }
12008
12009 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12010 {
12011 //these are here to bypass compiler warnings about unused arguments
12012 c=c;
12013
12014 if(msg==MSG_DRAW)
12015 {
12016 FONT *f = get_zc_font(font_lfont_l);
12017 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12018 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12019 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12020 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12021 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12022 }
12023
12024 return D_O_K;
12025 }
12026
12027 int32_t click_d_ctile_proc()
12028 {
12029 d_ctile_proc(MSG_CLICK,NULL,0);
12030 return D_REDRAW;
12031 }
12032
12033 int32_t click_d_combo_proc();
12034
12035 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12036 {
12037 if(index<0)
12038 {
12039 *list_size = bidcomboscripts_cnt;
12040 return NULL;
12041 }
12042
12043 return bidcomboscripts[index].first.c_str();
12044 }
12045 12 ListData comboscript_list(comboscriptdroplist, &font);
12046
12047 bool call_combo_editor(int32_t);
12048 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12049 {
12050 FONT* ofont = font;
12051 //CSet = cs;
12052 reset_combo_animations();
12053 reset_combo_animations2();
12054 bool edited = call_combo_editor(c);
12055 font = ofont;
12056
12057 if(freshen)
12058 {
12059 refresh(rALL);
12060 }
12061
12062 setup_combo_animations();
12063 setup_combo_animations2();
12064
12065 return edited;
12066 }
12067
12068 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12069 {
12070 switch(msg)
12071 {
12072 case MSG_CLICK:
12073 {
12074 int32_t cs = d->d2;
12075 int32_t f = 0;
12076
12077 if(select_tile(d->d1,f,1,cs,true))
12078 {
12079 int32_t ok=1;
12080
12081 if(newtilebuf[d->d1].format==tf8Bit)
12082 jwin_alert("Warning",
12083 "You have selected an 8-bit tile.",
12084 "It will not be drawn correctly",
12085 "on the file select screen.",
12086 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12087
12088 return D_REDRAW;
12089 }
12090 }
12091 break;
12092
12093 case MSG_DRAW:
12094 d->w = 32+4;
12095 d->h = 32+4;
12096
12097 BITMAP *buf = create_bitmap_ex(8,16,16);
12098 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12099
12100 if(buf && bigbmp)
12101 {
12102 clear_bitmap(buf);
12103 overtile16(buf,d->d1,0,0,d->fg,0);
12104 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12105 destroy_bitmap(buf);
12106 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12107 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12108 destroy_bitmap(bigbmp);
12109 }
12110
12111 break;
12112 }
12113
12114 return D_O_K;
12115 }
12116
12117 static DIALOG icon_dlg[] =
12118 {
12119 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12120 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12121 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12122 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12123 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12124 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12125 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12126 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12127 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12128 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12129 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12130 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12131 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12132 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12133 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12134 };
12135
12136 int32_t onIcons()
12137 {
12138 PALETTE pal;
12139 memcpy(pal,RAMpal,sizeof(RAMpal));
12140 icon_dlg[0].dp2=get_zc_font(font_lfont);
12141
12142 for(int32_t i=0; i<4; i++)
12143 {
12144 icon_dlg[i+2].d1 = QMisc.icons[i];
12145 icon_dlg[i+2].fg = i+6;
12146 load_cset(pal, i+6, pSprite(i+spICON1));
12147 }
12148
12149 zc_set_palette(pal);
12150
12151 large_dialog(icon_dlg);
12152
12153 int32_t ret = do_zqdialog(icon_dlg,7);
12154
12155 if(ret==6)
12156 {
12157 for(int32_t i=0; i<4; i++)
12158 {
12159 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12160 {
12161 QMisc.icons[i] = icon_dlg[i+2].d1;
12162 saved=false;
12163 }
12164 }
12165 }
12166
12167 zc_set_palette(RAMpal);
12168 return D_O_K;
12169 }
12170
12171 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12172 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12173 {
12174 if(msg == MSG_DRAW)
12175 {
12176 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12177 }
12178
12179 return D_O_K;
12180 }
12181
12182 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12183 {
12184 switch(msg)
12185 {
12186 case MSG_CLICK:
12187 {
12188 if((d->flags&D_NOCLICK))
12189 break;
12190
12191 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12192 int32_t combo2;
12193 int32_t cs;
12194
12195 if(CHECK_ALT) //place selected cmb/cs
12196 {
12197 if(gui_mouse_b()&1)
12198 {
12199 if(!CHECK_SHIFT)
12200 d->d1 = Combo;
12201 d->fg = CSet;
12202 }
12203
12204 return ret|D_REDRAW;
12205 }
12206 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12207 {
12208 d->d1=0;
12209 d->fg=0;
12210 return ret|D_REDRAW;
12211 }
12212 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12213 {
12214 combo2=d->d1;
12215 cs=d->fg;
12216
12217 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12218 {
12219 d->d1=combo2;
12220 d->fg=cs;
12221 }
12222
12223 return ret|D_REDRAW;
12224 }
12225 else return ret|D_REDRAWME;
12226 }
12227 break;
12228
12229 case MSG_DRAW:
12230 {
12231 d->w = 32;
12232 d->h = 32;
12233
12234 BITMAP *buf = create_bitmap_ex(8,16,16);
12235 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12236
12237 if(buf && bigbmp)
12238 {
12239 clear_bitmap(buf);
12240
12241 if(d->d1==-1) // Display curr_combo instead of combobuf
12242 {
12243 newcombo hold = combobuf[0];
12244 combobuf[0] = curr_combo;
12245 putcombo(buf,0,0,0,d->fg);
12246 combobuf[0] = hold;
12247 }
12248 else if(d->d1)
12249 {
12250 putcombo(buf,0,0,d->d1,d->fg);
12251 }
12252
12253 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12254 destroy_bitmap(buf);
12255 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12256 destroy_bitmap(bigbmp);
12257 }
12258 }
12259 break;
12260 }
12261 return D_O_K;
12262 }
12263
12264 // Hey, let's have a few hundred more lines of code, why not.
12265
12266 #define MR_4BIT 0
12267 #define MR_8BIT 1
12268
12269 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12270 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12271 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12272
12273 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12274 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12275
12276 static int32_t massRecolorDraggedColor=-1;
12277 static int32_t massRecolorCSet;
12278 static bool massRecolorIgnoreBlank=true;
12279 static byte massRecolorType=MR_4BIT;
12280
12281 // Shows the sets of colors to replace from/to.
12282 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12283 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12284 #define D_CSET D_USER
12285 #define D_SETTABLE (D_USER<<1)
12286 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12287 {
12288 BITMAP* bmp=screen;
12289 int32_t colorWidth=(d->w-4)/16;
12290 byte* colors=static_cast<byte*>(d->dp);
12291
12292 switch(msg)
12293 {
12294 case MSG_DRAW:
12295 {
12296 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12297
12298 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12299 for(int32_t c=0; c<16; c++)
12300 {
12301 rectfill(bmp,
12302 d->x+2+c*colorWidth, d->y+2,
12303 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12304 baseColor+colors[c]);
12305 }
12306 }
12307 break;
12308
12309 case MSG_LPRESS:
12310 {
12311 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12312
12313 if(x >= 0 && x < 16) //sanity check!
12314 {
12315 massRecolorDraggedColor=colors[x];
12316 }
12317 }
12318 break;
12319
12320 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12321 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12322 {
12323 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12324 if(x >= 0 && x < 16) //sanity check!
12325 {
12326 colors[x]=massRecolorDraggedColor;
12327 d->flags|=D_DIRTY;
12328 }
12329 }
12330 massRecolorDraggedColor=-1;
12331 break;
12332 }
12333
12334 return D_O_K;
12335 }
12336
12337 // Used for the full palette in 8-bit mode.
12338 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12339 {
12340 BITMAP* bmp=screen;
12341 int colorWidth=(d->w-4)/16;
12342 d->h = 4+(colorWidth*14);
12343 int colorHeight=colorWidth;
12344
12345 switch(msg)
12346 {
12347 case MSG_DRAW:
12348 {
12349 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12350 for(int cset=0; cset<=13; cset++)
12351 {
12352 for(int color=0; color<16; color++)
12353 {
12354 rectfill(bmp,
12355 d->x+2+color*colorWidth,
12356 d->y+2+cset*colorHeight,
12357 d->x+2+((color+1)*colorWidth)-1,
12358 d->y+2+((cset+1)*colorHeight)-1,
12359 cset*16+color);
12360 }
12361 }
12362 }
12363 break;
12364
12365 case MSG_LPRESS:
12366 {
12367 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12368 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12369 massRecolorDraggedColor=cset*16+color;
12370 }
12371 break;
12372 }
12373
12374 return D_O_K;
12375 }
12376
12377 static DIALOG recolor_4bit_dlg[] =
12378 {
12379 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12380 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12381
12382 // 1
12383 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12384 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12385 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12386 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12387
12388 // 5
12389 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12390 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12391 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12392 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12393 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12394 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12395 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12396 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12397 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12398 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12399 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12400 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12401 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12402 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12403 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12404
12405 // 20
12406 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12407 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12408 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12409 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12410 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12411
12412 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12413 };
12414
12415 #define MR4_SRC_COLORS 2
12416 #define MR4_DEST_COLORS 4
12417 #define MR4_8BIT_EFFECT_START 6
12418 #define MR4_IGNORE_BLANK 20
12419 #define MR4_RESET 21
12420 #define MR4_SWITCH 22
12421 #define MR4_OK 23
12422 #define MR4_CANCEL 24
12423
12424 static DIALOG recolor_8bit_dlg[] =
12425 {
12426 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12427 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12428
12429 // 1
12430 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12431 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12432 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12433 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12434 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12435
12436 // 6
12437 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12438 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12439 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12440 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12441 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12442
12443 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12444 };
12445
12446 #define MR8_SRC_COLORS 2
12447 #define MR8_DEST_COLORS 4
12448 #define MR8_PALETTE 5
12449 #define MR8_IGNORE_BLANK 6
12450 #define MR8_RESET 7
12451 #define MR8_SWITCH 8
12452 #define MR8_OK 9
12453 #define MR8_CANCEL 10
12454
12455 static void massRecolorInit(int32_t cset)
12456 {
12457 massRecolorDraggedColor=-1;
12458 massRecolorCSet=cset;
12459
12460 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12461 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12462
12463 for(int32_t i=0; i<=13; i++)
12464 {
12465 if((massRecolor8BitCSets&(1<<i))!=0)
12466 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12467 else
12468 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12469 }
12470
12471 if(massRecolorIgnoreBlank)
12472 {
12473 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12474 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12475 }
12476 else
12477 {
12478 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12479 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12480 }
12481
12482 large_dialog(recolor_4bit_dlg);
12483 large_dialog(recolor_8bit_dlg);
12484
12485 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12486 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12487 {
12488 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12489 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12490 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12491 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12492
12493 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12494 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12495 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12496 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12497 recolor_8bit_dlg[MR8_PALETTE].x++;
12498 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12499 recolor_8bit_dlg[MR8_PALETTE].y++;
12500 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12501 }
12502 }
12503
12504 static void massRecolorApplyChanges()
12505 {
12506 massRecolor8BitCSets=0;
12507 for(int32_t i=0; i<=13; i++)
12508 {
12509 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12510 massRecolor8BitCSets|=1<<i;
12511 }
12512
12513 if(massRecolorType==MR_4BIT)
12514 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12515 else
12516 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12517 }
12518
12519 static bool massRecolorSetup(int32_t cset)
12520 {
12521 massRecolorInit(cset);
12522
12523 // Remember the current colors in case the user cancels.
12524 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12525 for(int32_t i=0; i<16; i++)
12526 {
12527 oldDest4Bit[i]=massRecolorDest4Bit[i];
12528 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12529 oldDest8Bit[i]=massRecolorDest8Bit[i];
12530 }
12531
12532 byte type=massRecolorType;
12533 int32_t ret;
12534 do
12535 {
12536 HANDLE_CLOSE_ZQDLG();
12537 if(exiting_program) break;
12538 if(type==MR_4BIT)
12539 {
12540 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12541 if(ret==MR4_SWITCH)
12542 type=MR_8BIT;
12543 }
12544 else
12545 {
12546 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12547 if(ret==MR8_SWITCH)
12548 type=MR_4BIT;
12549 }
12550 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12551
12552 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12553 {
12554 for(int32_t i=0; i<16; i++)
12555 {
12556 massRecolorDest4Bit[i]=oldDest4Bit[i];
12557 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12558 massRecolorDest8Bit[i]=oldDest8Bit[i];
12559 }
12560 return false;
12561 }
12562
12563 // OK
12564 massRecolorType=type;
12565 massRecolorApplyChanges();
12566 return true;
12567 }
12568
12569 static void massRecolorApply4Bit(int32_t tile)
12570 {
12571 byte buf[256];
12572 unpack_tile(newtilebuf, tile, 0, true);
12573
12574 if(newtilebuf[tile].format==tf4Bit)
12575 {
12576 for(int32_t i=0; i<256; i++)
12577 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12578 }
12579 else // 8-bit
12580 {
12581 for(int32_t i=0; i<256; i++)
12582 {
12583 word cset=unpackbuf[i]>>4;
12584 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12585 {
12586 word color=unpackbuf[i]&15;
12587 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12588 }
12589 else
12590 buf[i]=unpackbuf[i];
12591 }
12592 }
12593
12594 pack_tile(newtilebuf, buf, tile);
12595 }
12596
12597 static void massRecolorApply8Bit(int32_t tile)
12598 {
12599 byte buf[256];
12600 unpack_tile(newtilebuf, tile, 0, true);
12601
12602 for(int32_t i=0; i<256; i++)
12603 {
12604 byte color=unpackbuf[i];
12605 for(int32_t j=0; j<16; j++)
12606 {
12607 if(massRecolorSrc8Bit[j]==color)
12608 {
12609 color=massRecolorDest8Bit[j];
12610 break;
12611 }
12612 }
12613 buf[i]=color;
12614 }
12615
12616 pack_tile(newtilebuf, buf, tile);
12617 }
12618
12619 static void massRecolorApply(int32_t tile)
12620 {
12621 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12622 return;
12623
12624 if(massRecolorType==MR_4BIT)
12625 massRecolorApply4Bit(tile);
12626 else // 8-bit
12627 {
12628 if(newtilebuf[tile].format==tf4Bit)
12629 return;
12630 massRecolorApply8Bit(tile);
12631 }
12632 }
12633
12634 static void massRecolorReset4Bit()
12635 {
12636 for(int32_t i=0; i<16; i++)
12637 massRecolorDest4Bit[i]=i;
12638 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12639 }
12640
12641 static void massRecolorReset8Bit()
12642 {
12643 for(int32_t i=0; i<16; i++)
12644 {
12645 massRecolorSrc8Bit[i]=0;
12646 massRecolorDest8Bit[i]=0;
12647 }
12648
12649 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12650 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12651 }
12652
12653 1 void center_zq_tiles_dialogs()
12654 {
12655 1 jwin_center_dialog(create_relational_tiles_dlg);
12656 1 jwin_center_dialog(icon_dlg);
12657 1 jwin_center_dialog(leech_dlg);
12658 1 jwin_center_dialog(move_textbox_list_dlg);
12659 1 jwin_center_dialog(recolor_4bit_dlg);
12660 1 jwin_center_dialog(recolor_8bit_dlg);
12661 1 }
12662
12663 //.ZCOMBO
12664
12665 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12666 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12667
12668 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12669 dword section_version, int32_t index, int32_t count)
12670 {
12671 byte tempbyte;
12672 newcombo temp_combo;
12673 for ( int32_t tilect = 0; tilect < count; tilect++ )
12674 {
12675 int32_t temp_trigflags[3] = {0};
12676 temp_combo.clear();
12677 combo_trigger& temp_trigger = temp_combo.triggers.emplace_back();
12678 if(!p_igetw(&temp_combo.tile,f))
12679 {
12680 return 0;
12681 }
12682 temp_combo.o_tile = temp_combo.tile;
12683
12684 if(!p_getc(&temp_combo.flip,f))
12685 {
12686 return 0;
12687 }
12688
12689 if(!p_getc(&temp_combo.walk,f))
12690 {
12691 return 0;
12692 }
12693
12694 if(!p_getc(&temp_combo.type,f))
12695 {
12696 return 0;
12697 }
12698
12699 if(!p_getc(&temp_combo.csets,f))
12700 {
12701 return 0;
12702 }
12703
12704 if(!p_getc(&temp_combo.frames,f))
12705 {
12706 return 0;
12707 }
12708
12709 if(!p_getc(&temp_combo.speed,f))
12710 {
12711 return 0;
12712 }
12713
12714 if(!p_igetw(&temp_combo.nextcombo,f))
12715 {
12716 return 0;
12717 }
12718
12719 if(!p_getc(&temp_combo.nextcset,f))
12720 {
12721 return 0;
12722 }
12723
12724 if(!p_getc(&temp_combo.flag,f))
12725 {
12726 return 0;
12727 }
12728
12729 if(!p_getc(&temp_combo.skipanim,f))
12730 {
12731 return 0;
12732 }
12733
12734 if(!p_igetw(&temp_combo.nexttimer,f))
12735 {
12736 return 0;
12737 }
12738
12739 if(!p_getc(&temp_combo.skipanimy,f))
12740 {
12741 return 0;
12742 }
12743
12744 if(!p_getc(&temp_combo.animflags,f))
12745 {
12746 return 0;
12747 }
12748
12749 //2.55 starts here
12750 if ( zversion >= 0x255 )
12751 {
12752 if ( section_version >= 12 )
12753 {
12754 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12755 {
12756 if(!p_igetl(&temp_combo.attributes[q],f))
12757 {
12758 return 0;
12759 }
12760 }
12761 if(!p_igetl(&temp_combo.usrflags,f))
12762 {
12763 return 0;
12764 }
12765 for ( int32_t q = 0; q < 3; q++ )
12766 {
12767 if(!p_igetl(&temp_trigflags[q],f))
12768 return 0;
12769 }
12770
12771 if(!p_igetl(&temp_trigger.triggerlevel,f))
12772 {
12773 return 0;
12774 }
12775 if(section_version >= 22)
12776 {
12777 if(!p_getc(&temp_trigger.triggerbtn,f))
12778 {
12779 return 0;
12780 }
12781 }
12782 if(section_version < 23)
12783 {
12784 switch(temp_combo.type) // TRIGFLAG_CMBTYPEFX now required for combotype-specific effects
12785 {
12786 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12787 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12788 case cTRIGGERGENERIC: case cCSWITCH:
12789 temp_trigflags[TRIGFLAG_CMBTYPEFX/32] |= 1 << (TRIGFLAG_CMBTYPEFX%32);
12790 }
12791 }
12792 if(section_version >= 24)
12793 {
12794 if(!p_getc(&temp_trigger.triggeritem,f))
12795 {
12796 return 0;
12797 }
12798 if(!p_getc(&tempbyte, f))
12799 return 0;
12800 temp_trigger.trigtimer = tempbyte;
12801 }
12802 if(section_version >= 25)
12803 {
12804 if(!p_getc(&temp_trigger.trigsfx,f))
12805 {
12806 return 0;
12807 }
12808 }
12809 else
12810 {
12811 switch(temp_combo.type)
12812 {
12813 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12814 if(!(temp_combo.usrflags & cflag3))
12815 temp_combo.attribytes[3] = WAV_DOOR;
12816 temp_combo.usrflags &= ~cflag3;
12817 break;
12818 }
12819 }
12820 if(section_version < 26)
12821 {
12822 if(temp_combo.type == cARMOS)
12823 {
12824 if(temp_combo.usrflags & cflag1)
12825 temp_combo.usrflags |= cflag3;
12826 }
12827 }
12828 if(section_version >= 27)
12829 {
12830 if(!p_igetl(&temp_trigger.trigchange,f))
12831 {
12832 return qe_invalid;
12833 }
12834 }
12835 else
12836 {
12837 if(temp_trigflags[0] & 0x00040000) //'next'
12838 temp_trigger.trigchange = 1;
12839 else if(temp_trigflags[0] & 0x00080000) //'prev'
12840 temp_trigger.trigchange = -1;
12841 else temp_trigger.trigchange = 0;
12842 temp_trigflags[0] &= ~(0x00040000|0x00080000);
12843 }
12844 if(section_version >= 29)
12845 {
12846 if(!p_igetw(&temp_trigger.trigprox,f))
12847 {
12848 return qe_invalid;
12849 }
12850 if(!p_getc(&tempbyte,f))
12851 return qe_invalid;
12852 temp_trigger.trigctr = tempbyte;
12853 if(!p_igetl(&temp_trigger.trigctramnt,f))
12854 {
12855 return qe_invalid;
12856 }
12857 }
12858 else
12859 {
12860 temp_trigger.trigprox = 0;
12861 temp_trigger.trigctr = 0;
12862 temp_trigger.trigctramnt = 0;
12863 }
12864 if(section_version >= 30)
12865 {
12866 if(!p_getc(&temp_trigger.triglbeam,f))
12867 {
12868 return qe_invalid;
12869 }
12870 }
12871 else temp_trigger.triglbeam = 0;
12872 if(section_version >= 31)
12873 {
12874 if(!p_getc(&temp_trigger.trigcschange,f))
12875 {
12876 return qe_invalid;
12877 }
12878 if(!p_igetw(&temp_trigger.spawnitem,f))
12879 {
12880 return qe_invalid;
12881 }
12882 if(!p_igetw(&temp_trigger.spawnenemy,f))
12883 {
12884 return qe_invalid;
12885 }
12886 if(!p_getc(&temp_trigger.exstate,f))
12887 {
12888 return qe_invalid;
12889 }
12890 if(!p_igetl(&temp_trigger.spawnip,f))
12891 {
12892 return qe_invalid;
12893 }
12894 if(!p_getc(&temp_trigger.trigcopycat,f))
12895 {
12896 return qe_invalid;
12897 }
12898 }
12899 else
12900 {
12901 temp_trigger.trigcschange = 0;
12902 temp_trigger.spawnitem = 0;
12903 temp_trigger.spawnenemy = 0;
12904 temp_trigger.exstate = -1;
12905 temp_trigger.spawnip = 0;
12906 temp_trigger.trigcopycat = 0;
12907 }
12908 if(section_version >= 32)
12909 {
12910 if(!p_getc(&temp_trigger.trigcooldown,f))
12911 {
12912 return qe_invalid;
12913 }
12914 }
12915 else
12916 {
12917 temp_trigger.trigcooldown = 0;
12918 }
12919 char label[12];
12920 label[11] = '\0';
12921 for ( int32_t q = 0; q < 11; q++ )
12922 {
12923 if(!p_getc(&label[q],f))
12924 {
12925 return 0;
12926 }
12927 }
12928 temp_combo.label = label;
12929 }
12930 if ( section_version >= 13 )
12931 {
12932 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12933 {
12934 if(!p_getc(&temp_combo.attribytes[q],f))
12935 {
12936 return 0;
12937 }
12938 }
12939
12940 }
12941 }
12942
12943 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12944 {
12945 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12946 {
12947 combobuf[index+(tilect)] = temp_combo;
12948 }
12949 }
12950
12951 temp_trigger.trigger_flags.clear();
12952 for(size_t q = 0; q < 32*3; ++q)
12953 {
12954 auto ind = q/32;
12955 auto bit = 1<<(q%32);
12956 if(temp_trigflags[ind] & bit)
12957 temp_trigger.trigger_flags.set(q, true);
12958 }
12959 }
12960
12961 return 1;
12962 }
12963
12964 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12965 {
12966 dword section_version=0;
12967 int32_t zversion = 0;
12968 int32_t zbuild = 0;
12969
12970 if(!p_igetl(&zversion,f))
12971 {
12972 return 0;
12973 }
12974 if(!p_igetl(&zbuild,f))
12975 {
12976 return 0;
12977 }
12978 if(!p_igetw(&section_version,f))
12979 {
12980 return 0;
12981 }
12982 if(!read_deprecated_section_cversion(f))
12983 {
12984 return 0;
12985 }
12986
12987 if ( zversion > ZELDA_VERSION )
12988 {
12989 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12990 return 0;
12991 }
12992
12993 else if ( ( section_version > V_COMBOS ))
12994 {
12995 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d)\n", section_version);
12996 return 0;
12997
12998 }
12999 else
13000 {
13001 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13002 }
13003
13004 int32_t index = 0;
13005 int32_t count = 0;
13006
13007 //tile id
13008 if(!p_igetl(&index,f))
13009 {
13010 return 0;
13011 }
13012 if(start > -1) index = start;
13013
13014 //tile count
13015 if(!p_igetl(&count,f))
13016 {
13017 return 0;
13018 }
13019 reset_combo_animations();
13020 reset_combo_animations2();
13021
13022 if(section_version < 33)
13023 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,index,count);
13024
13025 newcombo temp_combo;
13026 size_t end = index+count;
13027 for ( size_t q = index; q < end; q++ )
13028 {
13029 auto ret = readcombo_loop(f,section_version,temp_combo);
13030 if(ret) return 0;
13031
13032 if ( !(skip && q-1 < skip) )
13033 {
13034 if ( !nooverwrite || combobuf[q].is_blank() )
13035 {
13036 combobuf[q] = temp_combo;
13037 }
13038 }
13039 }
13040
13041 return 1;
13042 }
13043 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13044 {
13045 return readcombofile(f,skip,nooverwrite,start);
13046 }
13047 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13048 {
13049 dword section_version=V_COMBOS;
13050 int32_t zversion = ZELDA_VERSION;
13051 int32_t zbuild = VERSION_BUILD;
13052
13053 if(!p_iputl(zversion,f))
13054 {
13055 return 0;
13056 }
13057 if(!p_iputl(zbuild,f))
13058 {
13059 return 0;
13060 }
13061 if(!p_iputw(section_version,f))
13062 {
13063 return 0;
13064 }
13065
13066 if(!write_deprecated_section_cversion(section_version,f))
13067 {
13068 return 0;
13069 }
13070
13071 //start tile id
13072 if(!p_iputl(index,f))
13073 {
13074 return 0;
13075 }
13076
13077 //count
13078 if(!p_iputl(count,f))
13079 {
13080 return 0;
13081 }
13082 reset_combo_animations();
13083 reset_combo_animations2();
13084 size_t end = index+count;
13085 for(size_t q = index; q < end; ++q)
13086 {
13087 if(writecombo_loop(f, section_version, combobuf[q]))
13088 return 0;
13089 }
13090
13091 return 1;
13092
13093 }
13094
13095 //.ZALIAS
13096
13097
13098 //.ZALIAS
13099
13100 int32_t readcomboaliasfile(PACKFILE *f)
13101 {
13102 dword section_version=0;
13103 int32_t zversion = 0;
13104 int32_t zbuild = 0;
13105 word tempword = 0;
13106
13107 if(!p_igetl(&zversion,f))
13108 {
13109 return 0;
13110 }
13111 if(!p_igetl(&zbuild,f))
13112 {
13113 return 0;
13114 }
13115 if(!p_igetw(&section_version,f))
13116 {
13117 return 0;
13118 }
13119 if(!read_deprecated_section_cversion(f))
13120 {
13121 return 0;
13122 }
13123 al_trace("readoneweapon section_version: %d\n", section_version);
13124
13125 if ( zversion > ZELDA_VERSION )
13126 {
13127 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13128 return 0;
13129 }
13130
13131 else if ( ( section_version > V_COMBOALIASES ))
13132 {
13133 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13134 return 0;
13135
13136 }
13137 else
13138 {
13139 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13140 }
13141
13142 int32_t index = 0;
13143 int32_t count = 0;
13144 int32_t count2 = 0;
13145 byte tempcset = 0;
13146
13147 //tile id
13148 if(!p_igetl(&index,f))
13149 {
13150 return 0;
13151 }
13152 al_trace("Reading combo: index(%d)\n", index);
13153
13154 //tile count
13155 if(!p_igetl(&count,f))
13156 {
13157 return 0;
13158 }
13159 al_trace("Reading combo: count(%d)\n", count);
13160
13161 combo_alias temp_alias;
13162
13163 for ( int32_t tilect = 0; tilect < count; tilect++ )
13164 {
13165 temp_alias.clear();
13166 if(!p_igetw(&temp_alias.combo,f))
13167 {
13168 return 0;
13169 }
13170
13171 if(!p_getc(&temp_alias.cset,f))
13172 {
13173 return 0;
13174 }
13175
13176
13177
13178 if(!p_igetl(&count2,f))
13179 {
13180 return 0;
13181 }
13182 al_trace("Read, Combo alias count is: %d\n", count2);
13183 if(!p_getc(&temp_alias.width,f))
13184 {
13185 return 0;
13186 }
13187
13188 if(!p_getc(&temp_alias.height,f))
13189 {
13190 return 0;
13191 }
13192
13193 if(!p_getc(&temp_alias.layermask,f))
13194 {
13195 return 0;
13196 }
13197 //These values are flexible, and may differ in size, so we delete them
13198 //and recreate them at the correct size on the pointer.
13199 temp_alias.combos.clear();
13200 temp_alias.csets.clear();
13201 for(int32_t k=0; k<count2; k++)
13202 {
13203 if(!p_igetw(&tempword,f))
13204 {
13205 return 0;
13206 }
13207 else
13208 {
13209
13210
13211 temp_alias.combos[k] = tempword;
13212 }
13213 }
13214
13215 for(int32_t k=0; k<count2; k++)
13216 {
13217 if(!p_getc(&tempcset,f))
13218 //if(!p_getc(&temp_alias.csets[k],f))
13219 {
13220 return 0;
13221 }
13222 else
13223 {
13224
13225 temp_alias.csets[k] = tempcset;
13226 }
13227 }
13228 combo_aliases[index+(tilect)] = temp_alias;
13229 }
13230
13231 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13232
13233
13234 return 1;
13235
13236 }
13237
13238 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13239 {
13240 dword section_version=0;
13241 int32_t zversion = 0;
13242 int32_t zbuild = 0;
13243
13244 if(!p_igetl(&zversion,f))
13245 {
13246 return 0;
13247 }
13248 if(!p_igetl(&zbuild,f))
13249 {
13250 return 0;
13251 }
13252 if(!p_igetw(&section_version,f))
13253 {
13254 return 0;
13255 }
13256 if(!read_deprecated_section_cversion(f))
13257 {
13258 return 0;
13259 }
13260 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13261
13262 if ( zversion > ZELDA_VERSION )
13263 {
13264 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13265 return 0;
13266 }
13267 else if ( ( section_version > V_COMBOALIASES ))
13268 {
13269 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13270 return 0;
13271
13272 }
13273 else
13274 {
13275 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13276 }
13277
13278 int32_t index = 0;
13279 int32_t count = 0;
13280 int32_t count2 = 0;
13281 byte tempcset = 0;
13282 word tempword = 0;
13283
13284
13285 //tile id
13286 if(!p_igetl(&index,f))
13287 {
13288 return 0;
13289 }
13290 al_trace("Reading tile: index(%d)\n", index);
13291
13292 //tile count
13293 if(!p_igetl(&count,f))
13294 {
13295 return 0;
13296 }
13297 al_trace("Reading tile: count(%d)\n", count);
13298
13299
13300 combo_alias temp_alias;
13301
13302 for ( int32_t tilect = 0; tilect < count; tilect++ )
13303 {
13304 temp_alias.clear();
13305 if(!p_igetw(&temp_alias.combo,f))
13306 {
13307 return 0;
13308 }
13309
13310 if(!p_getc(&temp_alias.cset,f))
13311 {
13312 return 0;
13313 }
13314
13315 int32_t count2 = 0;
13316
13317 if(!p_igetl(&count2,f))
13318 {
13319 return 0;
13320 }
13321
13322 if(!p_getc(&temp_alias.width,f))
13323 {
13324 return 0;
13325 }
13326
13327 if(!p_getc(&temp_alias.height,f))
13328 {
13329 return 0;
13330 }
13331
13332 if(!p_getc(&temp_alias.layermask,f))
13333 {
13334 return 0;
13335 }
13336 //These values are flexible, and may differ in size, so we delete them
13337 //and recreate them at the correct size on the pointer.
13338 temp_alias.combos.clear();
13339 temp_alias.csets.clear();
13340
13341 for(int32_t k=0; k<count2; k++)
13342 {
13343 if(!p_igetw(&tempword,f))
13344 {
13345 return 0;
13346 }
13347 else
13348 {
13349 temp_alias.combos[k] = tempword;
13350 }
13351 }
13352
13353 for(int32_t k=0; k<count2; k++)
13354 {
13355 if(!p_getc(&tempcset,f))
13356 {
13357 return 0;
13358 }
13359 else
13360 {
13361 temp_alias.csets[k] = tempcset;
13362 }
13363 }
13364
13365 if ( start+(tilect) < MAXCOMBOALIASES )
13366 {
13367 combo_aliases[start + (tilect)] = temp_alias;
13368 }
13369 }
13370 return 1;
13371 }
13372 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13373 {
13374 al_trace("Running writecomboaliasfile\n");
13375 dword section_version=V_COMBOALIASES;
13376 int32_t zversion = ZELDA_VERSION;
13377 int32_t zbuild = VERSION_BUILD;
13378
13379 if(!p_iputl(zversion,f))
13380 {
13381 return 0;
13382 }
13383 if(!p_iputl(zbuild,f))
13384 {
13385 return 0;
13386 }
13387 if(!p_iputw(section_version,f))
13388 {
13389 return 0;
13390 }
13391
13392 if(!write_deprecated_section_cversion(section_version,f))
13393 {
13394 return 0;
13395 }
13396
13397 //start tile id
13398 if(!p_iputl(index,f))
13399 {
13400 return 0;
13401 }
13402
13403 //count
13404 if(!p_iputl(count,f))
13405 {
13406 return 0;
13407 }
13408
13409 for ( int32_t tilect = 0; tilect < count; tilect++ )
13410 {
13411
13412 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13413 {
13414 return 0;
13415 }
13416
13417 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13418 {
13419 return 0;
13420 }
13421
13422 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13423
13424 if(!p_iputl(count2,f))
13425 {
13426 return 0;
13427 }
13428 al_trace("Write`, Combo alias count is: %d\n", count2);
13429
13430 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13431 {
13432 return 0;
13433 }
13434
13435 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13436 {
13437 return 0;
13438 }
13439
13440 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13441 {
13442 return 0;
13443 }
13444
13445 for(int32_t k=0; k<count2; k++)
13446 {
13447 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13448 {
13449 return 0;
13450 }
13451 }
13452
13453 for(int32_t k=0; k<count2; k++)
13454 {
13455 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13456 {
13457 return 0;
13458 }
13459 }
13460 }
13461
13462 return 1;
13463
13464 }
13465